29#include "llvm/ADT/CachedHashString.h"
30#include "llvm/ADT/DenseSet.h"
31#include "llvm/ADT/SetVector.h"
32#include "llvm/ADT/SmallPtrSet.h"
33#include "llvm/ADT/SmallString.h"
34#include "llvm/IR/DataLayout.h"
35#include "llvm/IR/InlineAsm.h"
36#include "llvm/IR/IntrinsicInst.h"
37#include "llvm/IR/LLVMContext.h"
38#include "llvm/IR/Module.h"
39#include "llvm/Support/ScopedPrinter.h"
40#include "llvm/Support/raw_ostream.h"
51class ObjCCommonTypesHelper {
53 llvm::LLVMContext &VMContext;
63 llvm::FunctionCallee getMessageSendFn()
const {
66 llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy};
67 return CGM.CreateRuntimeFunction(
68 llvm::FunctionType::get(ObjectPtrTy, params,
true),
"objc_msgSend",
69 llvm::AttributeList::get(CGM.getLLVMContext(),
70 llvm::AttributeList::FunctionIndex,
71 llvm::Attribute::NonLazyBind));
79 llvm::FunctionCallee getMessageSendStretFn()
const {
80 llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy};
81 return CGM.CreateRuntimeFunction(
82 llvm::FunctionType::get(CGM.VoidTy, params,
true),
83 "objc_msgSend_stret");
91 llvm::FunctionCallee getMessageSendFpretFn()
const {
92 llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy};
93 return CGM.CreateRuntimeFunction(
94 llvm::FunctionType::get(CGM.DoubleTy, params,
true),
95 "objc_msgSend_fpret");
103 llvm::FunctionCallee getMessageSendFp2retFn()
const {
104 llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy};
105 llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
106 llvm::Type *resultType =
107 llvm::StructType::get(longDoubleType, longDoubleType);
109 return CGM.CreateRuntimeFunction(
110 llvm::FunctionType::get(resultType, params,
true),
111 "objc_msgSend_fp2ret");
119 llvm::FunctionCallee getMessageSendSuperFn()
const {
120 llvm::Type *params[] = {SuperPtrTy, SelectorPtrTy};
121 return CGM.CreateRuntimeFunction(
122 llvm::FunctionType::get(ObjectPtrTy, params,
true),
123 "objc_msgSendSuper");
130 llvm::FunctionCallee getMessageSendSuperFn2()
const {
131 llvm::Type *params[] = {SuperPtrTy, SelectorPtrTy};
132 return CGM.CreateRuntimeFunction(
133 llvm::FunctionType::get(ObjectPtrTy, params,
true),
134 "objc_msgSendSuper2");
141 llvm::FunctionCallee getMessageSendSuperStretFn()
const {
142 llvm::Type *params[] = {Int8PtrTy, SuperPtrTy, SelectorPtrTy};
143 return CGM.CreateRuntimeFunction(
144 llvm::FunctionType::get(CGM.VoidTy, params,
true),
145 "objc_msgSendSuper_stret");
152 llvm::FunctionCallee getMessageSendSuperStretFn2()
const {
153 llvm::Type *params[] = {Int8PtrTy, SuperPtrTy, SelectorPtrTy};
154 return CGM.CreateRuntimeFunction(
155 llvm::FunctionType::get(CGM.VoidTy, params,
true),
156 "objc_msgSendSuper2_stret");
159 llvm::FunctionCallee getMessageSendSuperFpretFn()
const {
161 return getMessageSendSuperFn();
164 llvm::FunctionCallee getMessageSendSuperFpretFn2()
const {
166 return getMessageSendSuperFn2();
170 CodeGen::CodeGenModule &CGM;
173 llvm::IntegerType *ShortTy, *IntTy, *LongTy;
174 llvm::PointerType *Int8PtrTy, *Int8PtrPtrTy;
175 llvm::PointerType *Int8PtrProgramASTy;
176 llvm::Type *IvarOffsetVarTy;
179 llvm::PointerType *ObjectPtrTy;
182 llvm::PointerType *PtrObjectPtrTy;
185 llvm::PointerType *SelectorPtrTy;
190 QualType SuperPtrCTy;
193 llvm::StructType *SuperTy;
195 llvm::PointerType *SuperPtrTy;
199 llvm::StructType *PropertyTy;
203 llvm::StructType *PropertyListTy;
205 llvm::PointerType *PropertyListPtrTy;
208 llvm::StructType *MethodTy;
213 llvm::PointerType *CachePtrTy;
215 llvm::FunctionCallee getGetPropertyFn() {
216 CodeGen::CodeGenTypes &Types = CGM.getTypes();
217 ASTContext &Ctx = CGM.getContext();
226 return CGM.CreateRuntimeFunction(FTy,
"objc_getProperty");
229 llvm::FunctionCallee getSetPropertyFn() {
230 CodeGen::CodeGenTypes &Types = CGM.getTypes();
231 ASTContext &Ctx = CGM.getContext();
244 return CGM.CreateRuntimeFunction(FTy,
"objc_setProperty");
247 llvm::FunctionCallee getOptimizedSetPropertyFn(
bool atomic,
bool copy) {
248 CodeGen::CodeGenTypes &Types = CGM.getTypes();
249 ASTContext &Ctx = CGM.getContext();
259 SmallVector<CanQualType, 4> Params;
262 Params.push_back(IdType);
263 Params.push_back(SelType);
264 Params.push_back(IdType);
270 name =
"objc_setProperty_atomic_copy";
271 else if (atomic && !copy)
272 name =
"objc_setProperty_atomic";
273 else if (!atomic && copy)
274 name =
"objc_setProperty_nonatomic_copy";
276 name =
"objc_setProperty_nonatomic";
278 return CGM.CreateRuntimeFunction(FTy, name);
281 llvm::FunctionCallee getCopyStructFn() {
282 CodeGen::CodeGenTypes &Types = CGM.getTypes();
283 ASTContext &Ctx = CGM.getContext();
285 SmallVector<CanQualType, 5> Params;
289 Params.push_back(Ctx.
BoolTy);
290 Params.push_back(Ctx.
BoolTy);
293 return CGM.CreateRuntimeFunction(FTy,
"objc_copyStruct");
300 llvm::FunctionCallee getCppAtomicObjectFunction() {
301 CodeGen::CodeGenTypes &Types = CGM.getTypes();
302 ASTContext &Ctx = CGM.getContext();
305 SmallVector<CanQualType, 3> Params;
311 return CGM.CreateRuntimeFunction(FTy,
"objc_copyCppObjectAtomic");
314 llvm::FunctionCallee getEnumerationMutationFn() {
315 CodeGen::CodeGenTypes &Types = CGM.getTypes();
316 ASTContext &Ctx = CGM.getContext();
318 SmallVector<CanQualType, 1> Params;
322 return CGM.CreateRuntimeFunction(FTy,
"objc_enumerationMutation");
325 llvm::FunctionCallee getLookUpClassFn() {
326 CodeGen::CodeGenTypes &Types = CGM.getTypes();
327 ASTContext &Ctx = CGM.getContext();
329 SmallVector<CanQualType, 1> Params;
332 llvm::FunctionType *FTy =
335 return CGM.CreateRuntimeFunction(FTy,
"objc_lookUpClass");
339 llvm::FunctionCallee getGcReadWeakFn() {
341 llvm::Type *args[] = {CGM.DefaultPtrTy};
342 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
343 return CGM.CreateRuntimeFunction(FTy,
"objc_read_weak");
347 llvm::FunctionCallee getGcAssignWeakFn() {
349 llvm::Type *args[] = {ObjectPtrTy, CGM.DefaultPtrTy};
350 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
351 return CGM.CreateRuntimeFunction(FTy,
"objc_assign_weak");
355 llvm::FunctionCallee getGcAssignGlobalFn() {
357 llvm::Type *args[] = {ObjectPtrTy, CGM.DefaultPtrTy};
358 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
359 return CGM.CreateRuntimeFunction(FTy,
"objc_assign_global");
363 llvm::FunctionCallee getGcAssignThreadLocalFn() {
365 llvm::Type *args[] = {ObjectPtrTy, CGM.DefaultPtrTy};
366 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
367 return CGM.CreateRuntimeFunction(FTy,
"objc_assign_threadlocal");
371 llvm::FunctionCallee getGcAssignIvarFn() {
373 llvm::Type *args[] = {ObjectPtrTy, CGM.DefaultPtrTy, CGM.PtrDiffTy};
374 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
375 return CGM.CreateRuntimeFunction(FTy,
"objc_assign_ivar");
379 llvm::FunctionCallee GcMemmoveCollectableFn() {
381 llvm::Type *args[] = {Int8PtrTy, Int8PtrTy, LongTy};
382 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args,
false);
383 return CGM.CreateRuntimeFunction(FTy,
"objc_memmove_collectable");
387 llvm::FunctionCallee getGcAssignStrongCastFn() {
389 llvm::Type *args[] = {ObjectPtrTy, CGM.DefaultPtrTy};
390 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
391 return CGM.CreateRuntimeFunction(FTy,
"objc_assign_strongCast");
395 llvm::FunctionCallee getExceptionThrowFn() {
397 llvm::Type *args[] = {ObjectPtrTy};
398 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, args,
false);
399 return CGM.CreateRuntimeFunction(FTy,
"objc_exception_throw");
403 llvm::FunctionCallee getExceptionRethrowFn() {
405 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy,
false);
406 return CGM.CreateRuntimeFunction(FTy,
"objc_exception_rethrow");
410 llvm::FunctionCallee getSyncEnterFn() {
412 llvm::Type *args[] = {ObjectPtrTy};
413 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.IntTy, args,
false);
414 return CGM.CreateRuntimeFunction(FTy,
"objc_sync_enter");
418 llvm::FunctionCallee getSyncExitFn() {
420 llvm::Type *args[] = {ObjectPtrTy};
421 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.IntTy, args,
false);
422 return CGM.CreateRuntimeFunction(FTy,
"objc_sync_exit");
425 llvm::FunctionCallee getSendFn(
bool IsSuper)
const {
426 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
429 llvm::FunctionCallee getSendFn2(
bool IsSuper)
const {
430 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
433 llvm::FunctionCallee getSendStretFn(
bool IsSuper)
const {
434 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
437 llvm::FunctionCallee getSendStretFn2(
bool IsSuper)
const {
438 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
441 llvm::FunctionCallee getSendFpretFn(
bool IsSuper)
const {
442 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
445 llvm::FunctionCallee getSendFpretFn2(
bool IsSuper)
const {
446 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
449 llvm::FunctionCallee getSendFp2retFn(
bool IsSuper)
const {
450 return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
453 llvm::FunctionCallee getSendFp2RetFn2(
bool IsSuper)
const {
454 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
457 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
462class ObjCTypesHelper :
public ObjCCommonTypesHelper {
465 llvm::StructType *SymtabTy;
467 llvm::PointerType *SymtabPtrTy;
469 llvm::StructType *ModuleTy;
472 llvm::StructType *ProtocolTy;
474 llvm::PointerType *ProtocolPtrTy;
477 llvm::StructType *ProtocolExtensionTy;
480 llvm::PointerType *ProtocolExtensionPtrTy;
483 llvm::StructType *MethodDescriptionTy;
486 llvm::StructType *MethodDescriptionListTy;
489 llvm::PointerType *MethodDescriptionListPtrTy;
491 llvm::StructType *ProtocolListTy;
493 llvm::PointerType *ProtocolListPtrTy;
495 llvm::StructType *CategoryTy;
497 llvm::StructType *ClassTy;
499 llvm::PointerType *ClassPtrTy;
501 llvm::StructType *ClassExtensionTy;
503 llvm::PointerType *ClassExtensionPtrTy;
505 llvm::StructType *IvarTy;
507 llvm::StructType *IvarListTy;
509 llvm::PointerType *IvarListPtrTy;
511 llvm::StructType *MethodListTy;
513 llvm::PointerType *MethodListPtrTy;
516 llvm::StructType *ExceptionDataTy;
519 llvm::FunctionCallee getExceptionTryEnterFn() {
522 llvm::FunctionType::get(CGM.
VoidTy, params,
false),
523 "objc_exception_try_enter");
527 llvm::FunctionCallee getExceptionTryExitFn() {
530 llvm::FunctionType::get(CGM.
VoidTy, params,
false),
531 "objc_exception_try_exit");
535 llvm::FunctionCallee getExceptionExtractFn() {
538 llvm::FunctionType::get(ObjectPtrTy, params,
false),
539 "objc_exception_extract");
543 llvm::FunctionCallee getExceptionMatchFn() {
544 llvm::Type *params[] = {ClassPtrTy, ObjectPtrTy};
546 llvm::FunctionType::get(CGM.
Int32Ty, params,
false),
547 "objc_exception_match");
551 llvm::FunctionCallee getSetJmpFn() {
555 llvm::FunctionType::get(CGM.
Int32Ty, params,
false),
"_setjmp",
557 llvm::AttributeList::FunctionIndex,
558 llvm::Attribute::NonLazyBind));
562 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
567class ObjCNonFragileABITypesHelper :
public ObjCCommonTypesHelper {
570 llvm::StructType *MethodListnfABITy;
573 llvm::PointerType *MethodListnfABIPtrTy;
576 llvm::StructType *ProtocolnfABITy;
579 llvm::PointerType *ProtocolnfABIPtrTy;
582 llvm::StructType *ProtocolListnfABITy;
585 llvm::PointerType *ProtocolListnfABIPtrTy;
588 llvm::StructType *ClassnfABITy;
591 llvm::PointerType *ClassnfABIPtrTy;
594 llvm::StructType *IvarnfABITy;
597 llvm::StructType *IvarListnfABITy;
600 llvm::PointerType *IvarListnfABIPtrTy;
603 llvm::StructType *ClassRonfABITy;
606 llvm::PointerType *ImpnfABITy;
609 llvm::StructType *CategorynfABITy;
618 llvm::StructType *MessageRefTy;
620 QualType MessageRefCTy;
623 llvm::Type *MessageRefPtrTy;
625 QualType MessageRefCPtrTy;
632 llvm::StructType *SuperMessageRefTy;
635 llvm::PointerType *SuperMessageRefPtrTy;
637 llvm::FunctionCallee getMessageSendFixupFn() {
639 llvm::Type *params[] = {ObjectPtrTy, MessageRefPtrTy};
641 llvm::FunctionType::get(ObjectPtrTy, params,
true),
642 "objc_msgSend_fixup");
645 llvm::FunctionCallee getMessageSendFpretFixupFn() {
647 llvm::Type *params[] = {ObjectPtrTy, MessageRefPtrTy};
649 llvm::FunctionType::get(ObjectPtrTy, params,
true),
650 "objc_msgSend_fpret_fixup");
653 llvm::FunctionCallee getMessageSendStretFixupFn() {
655 llvm::Type *params[] = {ObjectPtrTy, MessageRefPtrTy};
657 llvm::FunctionType::get(ObjectPtrTy, params,
true),
658 "objc_msgSend_stret_fixup");
661 llvm::FunctionCallee getMessageSendSuper2FixupFn() {
664 llvm::Type *params[] = {SuperPtrTy, SuperMessageRefPtrTy};
666 llvm::FunctionType::get(ObjectPtrTy, params,
true),
667 "objc_msgSendSuper2_fixup");
670 llvm::FunctionCallee getMessageSendSuper2StretFixupFn() {
673 llvm::Type *params[] = {SuperPtrTy, SuperMessageRefPtrTy};
675 llvm::FunctionType::get(ObjectPtrTy, params,
true),
676 "objc_msgSendSuper2_stret_fixup");
679 llvm::FunctionCallee getObjCEndCatchFn() {
684 llvm::FunctionCallee getObjCBeginCatchFn() {
685 llvm::Type *params[] = {Int8PtrTy};
687 llvm::FunctionType::get(Int8PtrTy, params,
false),
"objc_begin_catch");
695 llvm::FunctionCallee getLoadClassrefFn()
const {
701 llvm::Type *params[] = {Int8PtrPtrTy};
703 llvm::AttributeSet AS = llvm::AttributeSet::get(
705 llvm::Attribute::get(
C, llvm::Attribute::NonLazyBind),
706 llvm::Attribute::getWithMemoryEffects(
707 C, llvm::MemoryEffects::none()),
708 llvm::Attribute::get(
C, llvm::Attribute::NoUnwind),
711 llvm::FunctionType::get(ClassnfABIPtrTy, params,
false),
714 llvm::AttributeList::FunctionIndex, AS));
715 if (!CGM.
getTriple().isOSBinFormatCOFF())
717 ->setLinkage(llvm::Function::ExternalWeakLinkage);
722 llvm::StructType *EHTypeTy;
723 llvm::Type *EHTypePtrTy;
725 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
728enum class ObjCLabelType {
742 SKIP_SCAN(
unsigned _skip = 0,
unsigned _scan = 0)
743 : skip(_skip), scan(_scan) {}
751 enum BLOCK_LAYOUT_OPCODE {
758 BLOCK_LAYOUT_OPERATOR = 0,
764 BLOCK_LAYOUT_NON_OBJECT_BYTES = 1,
769 BLOCK_LAYOUT_NON_OBJECT_WORDS = 2,
773 BLOCK_LAYOUT_STRONG = 3,
776 BLOCK_LAYOUT_BYREF = 4,
780 BLOCK_LAYOUT_WEAK = 5,
784 BLOCK_LAYOUT_UNRETAINED = 6
802 enum BLOCK_LAYOUT_OPCODE opcode;
803 CharUnits block_var_bytepos;
804 CharUnits block_var_size;
805 RUN_SKIP(
enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
808 : opcode(
Opcode), block_var_bytepos(BytePos), block_var_size(
Size) {}
812 return block_var_bytepos <
b.block_var_bytepos;
817 llvm::LLVMContext &VMContext;
822 SmallVector<RUN_SKIP, 16> RunSkipBlockVars;
826 llvm::SetVector<IdentifierInfo *> LazySymbols;
832 llvm::SetVector<IdentifierInfo *> DefinedSymbols;
835 llvm::StringMap<llvm::GlobalVariable *> ClassNames;
838 llvm::DenseMap<Selector, llvm::GlobalVariable *> MethodVarNames;
841 llvm::SmallSetVector<llvm::CachedHashString, 16> DefinedCategoryNames;
845 llvm::StringMap<llvm::GlobalVariable *> MethodVarTypes;
849 llvm::DenseMap<const ObjCMethodDecl *, llvm::Function *> MethodDefinitions;
852 struct DirectMethodInfo {
855 llvm::Function *Thunk;
857 DirectMethodInfo(llvm::Function *Impl, llvm::Function *Thunk =
nullptr)
858 : Implementation(Impl), Thunk(Thunk) {}
863 llvm::DenseMap<const ObjCMethodDecl *, DirectMethodInfo>
864 DirectMethodDefinitions;
867 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> PropertyNames;
870 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> ClassReferences;
873 llvm::DenseMap<Selector, llvm::GlobalVariable *> SelectorReferences;
878 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> Protocols;
882 llvm::DenseSet<IdentifierInfo *> DefinedProtocols;
885 SmallVector<llvm::GlobalValue *, 16> DefinedClasses;
888 SmallVector<const ObjCInterfaceDecl *, 16> ImplementedClasses;
891 SmallVector<llvm::GlobalValue *, 16> DefinedNonLazyClasses;
894 SmallVector<llvm::GlobalValue *, 16> DefinedCategories;
897 SmallVector<llvm::GlobalValue *, 16> DefinedStubCategories;
900 SmallVector<llvm::GlobalValue *, 16> DefinedNonLazyCategories;
904 llvm::WeakTrackingVH ConstantStringClassRef;
907 llvm::StructType *NSConstantStringType =
nullptr;
909 llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap;
913 llvm::Constant *GetMethodVarName(Selector Sel);
914 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
920 llvm::Constant *GetMethodVarType(
const ObjCMethodDecl *D,
921 bool Extended =
false);
922 llvm::Constant *GetMethodVarType(
const FieldDecl *D);
926 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
929 llvm::Constant *GetPropertyTypeString(
const ObjCPropertyDecl *PD,
930 const Decl *Container);
935 llvm::Constant *GetClassName(StringRef RuntimeName);
937 llvm::Function *GetMethodDefinition(
const ObjCMethodDecl *MD);
946 llvm::Constant *BuildIvarLayout(
const ObjCImplementationDecl *OI,
947 CharUnits beginOffset, CharUnits endOffset,
950 llvm::Constant *BuildStrongIvarLayout(
const ObjCImplementationDecl *OI,
951 CharUnits beginOffset,
952 CharUnits endOffset) {
953 return BuildIvarLayout(OI, beginOffset, endOffset,
true,
false);
956 llvm::Constant *BuildWeakIvarLayout(
const ObjCImplementationDecl *OI,
957 CharUnits beginOffset,
960 return BuildIvarLayout(OI, beginOffset, endOffset,
false,
hasMRCWeakIvars);
967 CharUnits FieldOffset, CharUnits FieldSize);
969 void BuildRCBlockVarRecordLayout(
const RecordType *RT, CharUnits BytePos,
970 bool &HasUnion,
bool ByrefLayout =
false);
972 void BuildRCRecordLayout(
const llvm::StructLayout *RecLayout,
973 const RecordDecl *RD,
974 ArrayRef<const FieldDecl *> RecFields,
975 CharUnits BytePos,
bool &HasUnion,
bool ByrefLayout);
977 uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
979 llvm::Constant *getBitmapBlockLayout(
bool ComputeByrefLayout);
983 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
984 const ObjCCommonTypesHelper &ObjCTypes);
988 llvm::Constant *EmitPropertyList(Twine Name,
const Decl *Container,
989 const ObjCContainerDecl *OCD,
990 const ObjCCommonTypesHelper &ObjCTypes,
991 bool IsClassProperty);
996 EmitProtocolMethodTypes(Twine Name, ArrayRef<llvm::Constant *> MethodTypes,
997 const ObjCCommonTypesHelper &ObjCTypes);
1002 llvm::Constant *GetProtocolRef(
const ObjCProtocolDecl *PD);
1006 llvm::Value *EmitClassRefViaRuntime(CodeGenFunction &CGF,
1007 const ObjCInterfaceDecl *ID,
1008 ObjCCommonTypesHelper &ObjCTypes);
1010 std::string GetSectionName(StringRef Section, StringRef MachOAttributes);
1027 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
1028 ConstantStructBuilder &
Init,
1029 StringRef Section, CharUnits Align,
1031 llvm::GlobalVariable *CreateMetadataVar(Twine Name, llvm::Constant *
Init,
1032 StringRef Section, CharUnits Align,
1035 llvm::GlobalVariable *CreateCStringLiteral(StringRef Name,
1036 ObjCLabelType LabelType,
1037 bool ForceNonFragileABI =
false,
1038 bool NullTerminate =
true);
1041 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1042 ReturnValueSlot Return, QualType ResultType,
1043 Selector Sel, llvm::Value *Arg0,
1044 QualType Arg0Ty,
bool IsSuper,
1045 const CallArgList &CallArgs,
1046 const ObjCMethodDecl *OMD,
1047 const ObjCInterfaceDecl *ClassReceiver,
1048 const ObjCCommonTypesHelper &ObjCTypes);
1052 void EmitImageInfo();
1055 CGObjCCommonMac(CodeGen::CodeGenModule &cgm)
1056 : CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) {}
1058 bool isNonFragileABI()
const {
return ObjCABI == 2; }
1060 ConstantAddress GenerateConstantString(
const StringLiteral *SL)
override;
1061 ConstantAddress GenerateConstantNSString(
const StringLiteral *SL);
1064 GenerateMethod(
const ObjCMethodDecl *OMD,
1065 const ObjCContainerDecl *CD =
nullptr)
override;
1067 DirectMethodInfo &GenerateDirectMethod(
const ObjCMethodDecl *OMD,
1068 const ObjCContainerDecl *CD);
1073 llvm::Value *GenerateClassRealization(CodeGenFunction &CGF,
1074 llvm::Value *classObject,
1075 const ObjCInterfaceDecl *OID);
1077 void GenerateDirectMethodsPreconditionCheck(
1078 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
1079 const ObjCContainerDecl *CD)
override;
1081 void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
1082 const ObjCMethodDecl *OMD,
1083 const ObjCContainerDecl *CD)
override;
1085 void GenerateProtocol(
const ObjCProtocolDecl *PD)
override;
1091 virtual llvm::Constant *GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD) = 0;
1093 virtual llvm::Constant *getNSConstantStringClassRef() = 0;
1095 llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
1096 const CGBlockInfo &blockInfo)
override;
1097 llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
1098 const CGBlockInfo &blockInfo)
override;
1099 std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM,
1100 const CGBlockInfo &blockInfo)
override;
1102 llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
1103 QualType
T)
override;
1106 void fillRunSkipBlockVars(CodeGenModule &CGM,
const CGBlockInfo &blockInfo);
1111enum class MethodListType {
1112 CategoryInstanceMethods,
1113 CategoryClassMethods,
1116 ProtocolInstanceMethods,
1117 ProtocolClassMethods,
1118 OptionalProtocolInstanceMethods,
1119 OptionalProtocolClassMethods,
1124class ProtocolMethodLists {
1127 RequiredInstanceMethods,
1128 RequiredClassMethods,
1129 OptionalInstanceMethods,
1130 OptionalClassMethods
1132 enum { NumProtocolMethodLists = 4 };
1134 static MethodListType getMethodListKind(Kind
kind) {
1136 case RequiredInstanceMethods:
1137 return MethodListType::ProtocolInstanceMethods;
1138 case RequiredClassMethods:
1139 return MethodListType::ProtocolClassMethods;
1140 case OptionalInstanceMethods:
1141 return MethodListType::OptionalProtocolInstanceMethods;
1142 case OptionalClassMethods:
1143 return MethodListType::OptionalProtocolClassMethods;
1145 llvm_unreachable(
"bad kind");
1148 SmallVector<const ObjCMethodDecl *, 4> Methods[NumProtocolMethodLists];
1150 static ProtocolMethodLists get(
const ObjCProtocolDecl *PD) {
1151 ProtocolMethodLists result;
1153 for (
auto *MD : PD->
methods()) {
1155 (2 *
size_t(MD->isOptional())) + (
size_t(MD->isClassMethod()));
1156 result.Methods[index].push_back(MD);
1162 template <
class Self>
1163 SmallVector<llvm::Constant *, 8> emitExtendedTypesArray(
Self *self)
const {
1170 SmallVector<llvm::Constant *, 8> result;
1173 for (
auto &list : Methods) {
1174 for (
auto MD : list) {
1175 result.push_back(self->GetMethodVarType(MD,
true));
1182 template <
class Self>
1183 llvm::Constant *emitMethodList(
Self *self,
const ObjCProtocolDecl *PD,
1186 getMethodListKind(
kind), Methods[
kind]);
1192class CGObjCMac :
public CGObjCCommonMac {
1194 friend ProtocolMethodLists;
1196 ObjCTypesHelper ObjCTypes;
1200 void EmitModuleInfo();
1204 llvm::Constant *EmitModuleSymbols();
1208 void FinishModule();
1213 llvm::Constant *EmitClassExtension(
const ObjCImplementationDecl *ID,
1214 CharUnits instanceSize,
1219 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
const ObjCInterfaceDecl *ID);
1221 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, IdentifierInfo *II);
1223 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF)
override;
1226 llvm::Value *EmitSuperClassRef(
const ObjCInterfaceDecl *ID);
1233 llvm::Constant *EmitIvarList(
const ObjCImplementationDecl *ID,
bool ForClass);
1238 llvm::Constant *EmitMetaClassRef(
const ObjCInterfaceDecl *ID);
1242 llvm::Constant *EmitMetaClass(
const ObjCImplementationDecl *ID,
1243 llvm::Constant *Protocols,
1244 ArrayRef<const ObjCMethodDecl *> Methods);
1246 void emitMethodConstant(ConstantArrayBuilder &builder,
1247 const ObjCMethodDecl *MD);
1249 void emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
1250 const ObjCMethodDecl *MD);
1254 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1255 ArrayRef<const ObjCMethodDecl *> Methods);
1260 llvm::Constant *GetOrEmitProtocol(
const ObjCProtocolDecl *PD)
override;
1266 llvm::Constant *GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD)
override;
1272 llvm::Constant *EmitProtocolExtension(
const ObjCProtocolDecl *PD,
1273 const ProtocolMethodLists &methodLists);
1277 llvm::Constant *EmitProtocolList(Twine Name,
1283 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1284 ConstantAddress EmitSelectorAddr(Selector Sel);
1287 CGObjCMac(CodeGen::CodeGenModule &cgm);
1289 llvm::Constant *getNSConstantStringClassRef()
override;
1291 llvm::Function *ModuleInitFunction()
override;
1293 CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1294 ReturnValueSlot Return,
1295 QualType ResultType, Selector Sel,
1296 llvm::Value *Receiver,
1297 const CallArgList &CallArgs,
1298 const ObjCInterfaceDecl *
Class,
1299 const ObjCMethodDecl *
Method)
override;
1301 CodeGen::RValue GenerateMessageSendSuper(
1302 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return,
1303 QualType ResultType, Selector Sel,
const ObjCInterfaceDecl *
Class,
1304 bool isCategoryImpl, llvm::Value *Receiver,
bool IsClassMessage,
1305 const CallArgList &CallArgs,
const ObjCMethodDecl *
Method)
override;
1307 llvm::Value *GetClass(CodeGenFunction &CGF,
1308 const ObjCInterfaceDecl *ID)
override;
1310 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel)
override;
1311 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel)
override;
1315 llvm::Value *GetSelector(CodeGenFunction &CGF,
1316 const ObjCMethodDecl *
Method)
override;
1318 llvm::Constant *GetEHType(QualType
T)
override;
1320 void GenerateCategory(
const ObjCCategoryImplDecl *CMD)
override;
1322 void GenerateClass(
const ObjCImplementationDecl *ClassDecl)
override;
1324 void RegisterAlias(
const ObjCCompatibleAliasDecl *OAD)
override {}
1326 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1327 const ObjCProtocolDecl *PD)
override;
1329 llvm::FunctionCallee GetPropertyGetFunction()
override;
1330 llvm::FunctionCallee GetPropertySetFunction()
override;
1331 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
1332 bool copy)
override;
1333 llvm::FunctionCallee GetGetStructFunction()
override;
1334 llvm::FunctionCallee GetSetStructFunction()
override;
1335 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override;
1336 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override;
1337 llvm::FunctionCallee EnumerationMutationFunction()
override;
1339 void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1340 const ObjCAtTryStmt &S)
override;
1341 void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1342 const ObjCAtSynchronizedStmt &S)
override;
1343 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
const Stmt &S);
1344 void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
const ObjCAtThrowStmt &S,
1345 bool ClearInsertionPoint =
true)
override;
1346 llvm::Value *EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
1347 Address AddrWeakObj)
override;
1348 void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
1349 Address dst)
override;
1350 void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
1351 Address dest,
bool threadlocal =
false)
override;
1352 void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
1353 Address dest, llvm::Value *ivarOffset)
override;
1354 void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
1355 Address dest)
override;
1356 void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, Address dest,
1357 Address src, llvm::Value *size)
override;
1359 LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1360 llvm::Value *BaseValue,
const ObjCIvarDecl *Ivar,
1361 unsigned CVRQualifiers)
override;
1362 llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1364 const ObjCIvarDecl *Ivar)
override;
1367class CGObjCNonFragileABIMac :
public CGObjCCommonMac {
1369 friend ProtocolMethodLists;
1370 ObjCNonFragileABITypesHelper ObjCTypes;
1371 llvm::GlobalVariable *ObjCEmptyCacheVar;
1372 llvm::Constant *ObjCEmptyVtableVar;
1375 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> SuperClassReferences;
1378 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> MetaClassReferences;
1381 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> EHTypeReferences;
1385 llvm::DenseSet<Selector> VTableDispatchMethods;
1388 std::vector<llvm::GlobalValue *> DefinedMetaClasses;
1392 bool isVTableDispatchedSelector(Selector Sel);
1396 void FinishNonFragileABIModule();
1400 void AddModuleClassList(ArrayRef<llvm::GlobalValue *> Container,
1401 StringRef SymbolName, StringRef SectionName);
1403 llvm::GlobalVariable *
1404 BuildClassRoTInitializer(
unsigned flags,
unsigned InstanceStart,
1405 unsigned InstanceSize,
1406 const ObjCImplementationDecl *ID);
1407 llvm::GlobalVariable *
1408 BuildClassObject(
const ObjCInterfaceDecl *CI,
bool isMetaclass,
1409 llvm::Constant *IsAGV, llvm::Constant *SuperClassGV,
1412 void emitMethodConstant(ConstantArrayBuilder &builder,
1413 const ObjCMethodDecl *MD,
bool forProtocol);
1417 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1418 ArrayRef<const ObjCMethodDecl *> Methods);
1425 llvm::Constant *EmitIvarList(
const ObjCImplementationDecl *ID);
1427 llvm::Constant *EmitIvarOffsetVar(
const ObjCInterfaceDecl *ID,
1428 const ObjCIvarDecl *Ivar,
1429 unsigned long int offset);
1434 llvm::Constant *GetOrEmitProtocol(
const ObjCProtocolDecl *PD)
override;
1440 llvm::Constant *GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD)
override;
1444 llvm::Constant *EmitProtocolList(Twine Name,
1448 CodeGen::RValue EmitVTableMessageSend(
1449 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return,
1450 QualType ResultType, Selector Sel, llvm::Value *Receiver, QualType Arg0Ty,
1451 bool IsSuper,
const CallArgList &CallArgs,
const ObjCMethodDecl *
Method);
1455 llvm::Constant *GetClassGlobal(StringRef Name,
1457 bool Weak =
false,
bool DLLImport =
false);
1458 llvm::Constant *GetClassGlobal(
const ObjCInterfaceDecl *ID,
bool isMetaclass,
1461 llvm::Constant *GetClassGlobalForClassRef(
const ObjCInterfaceDecl *ID);
1463 llvm::Value *EmitLoadOfClassRef(CodeGenFunction &CGF,
1464 const ObjCInterfaceDecl *ID,
1465 llvm::GlobalVariable *Entry);
1469 llvm::Value *EmitClassRef(CodeGenFunction &CGF,
const ObjCInterfaceDecl *ID);
1471 llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, IdentifierInfo *II,
1472 const ObjCInterfaceDecl *ID);
1474 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF)
override;
1478 llvm::Value *EmitSuperClassRef(CodeGenFunction &CGF,
1479 const ObjCInterfaceDecl *ID);
1483 llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF,
1484 const ObjCInterfaceDecl *ID,
bool Weak);
1489 llvm::GlobalVariable *ObjCIvarOffsetVariable(
const ObjCInterfaceDecl *ID,
1490 const ObjCIvarDecl *Ivar);
1494 llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
1495 ConstantAddress EmitSelectorAddr(Selector Sel);
1499 llvm::Constant *GetInterfaceEHType(
const ObjCInterfaceDecl *ID,
1502 StringRef getMetaclassSymbolPrefix()
const {
return "OBJC_METACLASS_$_"; }
1504 StringRef getClassSymbolPrefix()
const {
return "OBJC_CLASS_$_"; }
1506 void GetClassSizeInfo(
const ObjCImplementationDecl *OID,
1507 uint32_t &InstanceStart, uint32_t &InstanceSize);
1522 bool ImplementationIsNonLazy(
const ObjCImplDecl *OD)
const;
1524 bool IsIvarOffsetKnownIdempotent(
const CodeGen::CodeGenFunction &CGF,
1525 const ObjCIvarDecl *IV) {
1540 if (
const ObjCMethodDecl *MD =
1541 dyn_cast_or_null<ObjCMethodDecl>(CGF.
CurFuncDecl))
1542 if (MD->isInstanceMethod() && !MD->isDirectMethod())
1543 if (
const ObjCInterfaceDecl *ID = MD->getClassInterface())
1548 bool isClassLayoutKnownStatically(
const ObjCInterfaceDecl *ID) {
1551 assert(ID !=
nullptr &&
"Passed a null class to check layout");
1552 for (;
ID !=
nullptr;
ID =
ID->getSuperClass()) {
1555 if (
ID->getIdentifier()->getName() ==
"NSObject")
1560 if (!
ID->getImplementation())
1569 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
1571 llvm::Constant *getNSConstantStringClassRef()
override;
1573 llvm::Function *ModuleInitFunction()
override;
1575 CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
1576 ReturnValueSlot Return,
1577 QualType ResultType, Selector Sel,
1578 llvm::Value *Receiver,
1579 const CallArgList &CallArgs,
1580 const ObjCInterfaceDecl *
Class,
1581 const ObjCMethodDecl *
Method)
override;
1583 CodeGen::RValue GenerateMessageSendSuper(
1584 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return,
1585 QualType ResultType, Selector Sel,
const ObjCInterfaceDecl *
Class,
1586 bool isCategoryImpl, llvm::Value *Receiver,
bool IsClassMessage,
1587 const CallArgList &CallArgs,
const ObjCMethodDecl *
Method)
override;
1589 llvm::Value *GetClass(CodeGenFunction &CGF,
1590 const ObjCInterfaceDecl *ID)
override;
1592 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel)
override {
1593 return EmitSelector(CGF, Sel);
1595 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel)
override {
1596 return EmitSelectorAddr(Sel);
1601 llvm::Value *GetSelector(CodeGenFunction &CGF,
1602 const ObjCMethodDecl *
Method)
override {
1603 return EmitSelector(CGF,
Method->getSelector());
1606 void GenerateCategory(
const ObjCCategoryImplDecl *CMD)
override;
1608 void GenerateClass(
const ObjCImplementationDecl *ClassDecl)
override;
1610 void RegisterAlias(
const ObjCCompatibleAliasDecl *OAD)
override {}
1612 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1613 const ObjCProtocolDecl *PD)
override;
1615 llvm::Constant *GetEHType(QualType
T)
override;
1617 llvm::FunctionCallee GetPropertyGetFunction()
override {
1618 return ObjCTypes.getGetPropertyFn();
1620 llvm::FunctionCallee GetPropertySetFunction()
override {
1621 return ObjCTypes.getSetPropertyFn();
1624 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
1625 bool copy)
override {
1626 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1629 llvm::FunctionCallee GetSetStructFunction()
override {
1630 return ObjCTypes.getCopyStructFn();
1633 llvm::FunctionCallee GetGetStructFunction()
override {
1634 return ObjCTypes.getCopyStructFn();
1637 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override {
1638 return ObjCTypes.getCppAtomicObjectFunction();
1641 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override {
1642 return ObjCTypes.getCppAtomicObjectFunction();
1645 llvm::FunctionCallee EnumerationMutationFunction()
override {
1646 return ObjCTypes.getEnumerationMutationFn();
1649 void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1650 const ObjCAtTryStmt &S)
override;
1651 void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1652 const ObjCAtSynchronizedStmt &S)
override;
1653 void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
const ObjCAtThrowStmt &S,
1654 bool ClearInsertionPoint =
true)
override;
1655 llvm::Value *EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
1656 Address AddrWeakObj)
override;
1657 void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
1658 Address edst)
override;
1659 void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
1660 Address dest,
bool threadlocal =
false)
override;
1661 void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
1662 Address dest, llvm::Value *ivarOffset)
override;
1663 void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
1664 Address dest)
override;
1665 void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, Address dest,
1666 Address src, llvm::Value *size)
override;
1667 LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
1668 llvm::Value *BaseValue,
const ObjCIvarDecl *Ivar,
1669 unsigned CVRQualifiers)
override;
1670 llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1672 const ObjCIvarDecl *Ivar)
override;
1677struct NullReturnState {
1678 llvm::BasicBlock *NullBB =
nullptr;
1679 NullReturnState() =
default;
1682 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
1692 CGF.
Builder.CreateCondBr(isNull, NullBB, callBB);
1700 RValue complete(CodeGenFunction &CGF, ReturnValueSlot returnSlot,
1701 RValue result, QualType resultType,
1702 const CallArgList &CallArgs,
const ObjCMethodDecl *
Method) {
1709 llvm::BasicBlock *contBB =
nullptr;
1712 llvm::BasicBlock *callBB = CGF.
Builder.GetInsertBlock();
1727 assert(CGF.
Builder.GetInsertBlock() == NullBB);
1749 llvm::PHINode *phi = CGF.
Builder.CreatePHI(null->getType(), 2);
1751 phi->addIncoming(null, NullBB);
1760 assert(result.
isAggregate() &&
"null init of non-aggregate result?");
1773 llvm::Type *scalarTy = callResult.first->getType();
1774 llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
1777 llvm::PHINode *real = CGF.
Builder.CreatePHI(scalarTy, 2);
1778 real->addIncoming(callResult.first, callBB);
1779 real->addIncoming(scalarZero, NullBB);
1780 llvm::PHINode *imag = CGF.
Builder.CreatePHI(scalarTy, 2);
1781 imag->addIncoming(callResult.second, callBB);
1782 imag->addIncoming(scalarZero, NullBB);
1793 llvm::GlobalVariable *
C,
unsigned idx0,
1795 llvm::Value *Idxs[] = {
1796 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1797 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)};
1798 return llvm::ConstantExpr::getGetElementPtr(
C->getValueType(),
C, Idxs);
1805 if (OID->
hasAttr<ObjCExceptionAttr>())
1812static llvm::GlobalValue::LinkageTypes
1814 if (CGM.
getTriple().isOSBinFormatMachO() &&
1815 (Section.empty() || Section.starts_with(
"__DATA")))
1816 return llvm::GlobalValue::InternalLinkage;
1817 return llvm::GlobalValue::PrivateLinkage;
1821static llvm::GlobalVariable *
1824 std::string SectionName;
1825 if (CGM.
getTriple().isOSBinFormatMachO())
1826 SectionName =
"__DATA, __objc_const";
1827 auto *GV = Builder.finishAndCreateGlobal(
1830 GV->setSection(SectionName);
1837 : CGObjCCommonMac(cgm), ObjCTypes(cgm) {
1846 return EmitClassRef(CGF, ID);
1850llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel) {
1851 return EmitSelector(CGF, Sel);
1853Address CGObjCMac::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
1854 return EmitSelectorAddr(Sel);
1856llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF,
1857 const ObjCMethodDecl *
Method) {
1858 return EmitSelector(CGF,
Method->getSelector());
1861llvm::Constant *CGObjCMac::GetEHType(QualType
T) {
1873 llvm_unreachable(
"asking for catch type for ObjC type in fragile runtime");
1896CGObjCCommonMac::GenerateConstantString(
const StringLiteral *SL) {
1899 : GenerateConstantNSString(SL));
1902static llvm::StringMapEntry<llvm::GlobalVariable *> &
1905 StringRef String = Literal->getString();
1906 StringLength = String.size();
1907 return *Map.insert(std::make_pair(String,
nullptr)).first;
1910llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
1911 if (llvm::Value *
V = ConstantStringClassRef)
1915 std::string str = StringClass.empty() ?
"_NSConstantStringClassReference"
1916 :
"_" + StringClass +
"ClassReference";
1918 llvm::Type *PTy = llvm::ArrayType::get(CGM.
IntTy, 0);
1920 ConstantStringClassRef = GV;
1924llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
1925 if (llvm::Value *
V = ConstantStringClassRef)
1929 std::string str = StringClass.empty() ?
"OBJC_CLASS_$_NSConstantString"
1930 :
"OBJC_CLASS_$_" + StringClass;
1932 ConstantStringClassRef = GV;
1937CGObjCCommonMac::GenerateConstantNSString(
const StringLiteral *Literal) {
1938 unsigned StringLength = 0;
1939 llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
1942 if (
auto *
C = Entry.second)
1943 return ConstantAddress(
C,
C->getValueType(),
1947 llvm::Constant *
Class = getNSConstantStringClassRef();
1950 if (!NSConstantStringType) {
1951 NSConstantStringType =
1953 "struct.__builtin_NSString");
1956 ConstantInitBuilder Builder(CGM);
1957 auto Fields = Builder.beginStruct(NSConstantStringType);
1960 Fields.addSignedPointer(
Class,
1962 GlobalDecl(), QualType());
1966 llvm::ConstantDataArray::getString(VMContext, Entry.first());
1968 llvm::GlobalValue::LinkageTypes
Linkage = llvm::GlobalValue::PrivateLinkage;
1969 bool isConstant = !CGM.
getLangOpts().WritableStrings;
1971 auto *GV =
new llvm::GlobalVariable(CGM.
getModule(),
C->getType(), isConstant,
1973 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1976 GV->setAlignment(llvm::Align(1));
1980 Fields.addInt(CGM.
IntTy, StringLength);
1984 GV = Fields.finishAndCreateGlobal(
"_unnamed_nsstring_", Alignment,
1986 llvm::GlobalVariable::PrivateLinkage);
1987 const char *NSStringSection =
"__OBJC,__cstring_object,regular,no_dead_strip";
1988 const char *NSStringNonFragileABISection =
1989 "__DATA,__objc_stringobj,regular,no_dead_strip";
1992 ? NSStringNonFragileABISection
1996 return ConstantAddress(GV, GV->getValueType(), Alignment);
2004CodeGen::RValue CGObjCMac::GenerateMessageSendSuper(
2005 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
2006 Selector Sel,
const ObjCInterfaceDecl *
Class,
bool isCategoryImpl,
2007 llvm::Value *Receiver,
bool IsClassMessage,
2008 const CodeGen::CallArgList &CallArgs,
const ObjCMethodDecl *
Method) {
2013 llvm::Value *ReceiverAsObject =
2014 CGF.
Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
2019 llvm::Type *ClassTyPtr = llvm::PointerType::getUnqual(VMContext);
2021 if (IsClassMessage) {
2022 if (isCategoryImpl) {
2029 Target = EmitClassRef(CGF,
Class->getSuperClass());
2034 llvm::Constant *MetaClassPtr = EmitMetaClassRef(
Class);
2035 llvm::Value *SuperPtr =
2041 }
else if (isCategoryImpl)
2042 Target = EmitClassRef(CGF,
Class->getSuperClass());
2044 llvm::Value *ClassPtr = EmitSuperClassRef(
Class);
2051 llvm::Type *ClassTy =
2055 return EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper.
getPointer(),
2056 ObjCTypes.SuperPtrCTy,
true, CallArgs,
Method,
Class,
2061CodeGen::RValue CGObjCMac::GenerateMessageSend(
2062 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
2063 Selector Sel, llvm::Value *Receiver,
const CallArgList &CallArgs,
2064 const ObjCInterfaceDecl *
Class,
const ObjCMethodDecl *
Method) {
2065 return EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
2070CodeGen::RValue CGObjCCommonMac::EmitMessageSend(
2071 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
2072 Selector Sel, llvm::Value *Arg0, QualType Arg0Ty,
bool IsSuper,
2073 const CallArgList &CallArgs,
const ObjCMethodDecl *
Method,
2074 const ObjCInterfaceDecl *ClassReceiver,
2075 const ObjCCommonTypesHelper &ObjCTypes) {
2076 CodeGenTypes &Types = CGM.
getTypes();
2078 llvm::Value *SelValue = llvm::UndefValue::get(Types.
ConvertType(selTy));
2080 CallArgList ActualArgs;
2082 Arg0 = CGF.
Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
2089 MessageSendInfo MSI = getMessageSendInfo(
Method, ResultType, ActualArgs);
2094 "Result type mismatch!");
2096 bool ReceiverCanBeNull =
2097 canMessageReceiverBeNull(CGF,
Method, IsSuper, ClassReceiver, Arg0);
2099 bool RequiresNullCheck =
false;
2100 bool RequiresSelValue =
true;
2102 llvm::FunctionCallee
Fn =
nullptr;
2105 auto Info = GenerateDirectMethod(
Method,
Method->getClassInterface());
2106 Fn = Info.Implementation;
2109 RequiresSelValue =
false;
2111 if (ReceiverCanBeNull)
2112 RequiresNullCheck =
true;
2113 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
2114 : ObjCTypes.getSendStretFn(IsSuper);
2116 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
2117 : ObjCTypes.getSendFpretFn(IsSuper);
2119 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
2120 : ObjCTypes.getSendFp2retFn(IsSuper);
2125 RequiresNullCheck =
true;
2126 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
2127 : ObjCTypes.getSendFn(IsSuper);
2132 CGF.
Builder.CreateBitCast(
Fn.getCallee(), MSI.MessengerType));
2137 RequiresNullCheck =
false;
2140 if (!RequiresNullCheck &&
Method &&
Method->hasParamDestroyedInCallee())
2141 RequiresNullCheck =
true;
2143 NullReturnState nullReturn;
2144 if (RequiresNullCheck) {
2145 nullReturn.init(CGF, Arg0);
2149 if (RequiresSelValue) {
2150 SelValue = GetSelector(CGF, Sel);
2151 ActualArgs[1] = CallArg(
RValue::get(SelValue), selTy);
2154 llvm::CallBase *CallSite;
2157 CGF.
EmitCall(MSI.CallInfo, Callee, Return, ActualArgs, &CallSite);
2161 if (
Method &&
Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
2162 CallSite->setDoesNotReturn();
2165 return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs,
2166 RequiresNullCheck ?
Method :
nullptr);
2170 bool pointee =
false) {
2184 switch (ownership) {
2192 llvm_unreachable(
"autoreleasing ivar?");
2194 llvm_unreachable(
"known nonzero");
2196 llvm_unreachable(
"bad objc ownership");
2216 IvarInfo(CharUnits offset, uint64_t sizeInWords)
2217 : Offset(offset), SizeInWords(sizeInWords) {}
2220 bool operator<(
const IvarInfo &other)
const {
return Offset < other.Offset; }
2224class IvarLayoutBuilder {
2229 CharUnits InstanceBegin;
2232 CharUnits InstanceEnd;
2235 bool ForStrongLayout;
2238 bool IsDisordered =
false;
2240 llvm::SmallVector<IvarInfo, 8> IvarsInfo;
2243 IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin,
2244 CharUnits instanceEnd,
bool forStrongLayout)
2245 : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
2246 ForStrongLayout(forStrongLayout) {}
2248 void visitRecord(
const RecordType *RT, CharUnits offset);
2250 template <
class Iterator,
class GetOffsetFn>
2251 void visitAggregate(Iterator begin, Iterator end, CharUnits aggrOffset,
2252 const GetOffsetFn &getOffset);
2254 void visitField(
const FieldDecl *field, CharUnits offset);
2257 void visitBlock(
const CGBlockInfo &blockInfo);
2260 bool hasBitmapData()
const {
return !IvarsInfo.empty(); }
2262 llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
2263 llvm::SmallVectorImpl<unsigned char> &buffer);
2265 static void dump(ArrayRef<unsigned char> buffer) {
2266 const unsigned char *
s = buffer.data();
2267 for (
unsigned i = 0, e = buffer.size(); i < e; i++)
2269 printf(
"0x0%x%s",
s[i],
s[i] != 0 ?
", " :
"");
2271 printf(
"0x%x%s",
s[i],
s[i] != 0 ?
", " :
"");
2278CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
2279 const CGBlockInfo &blockInfo) {
2281 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2282 if (CGM.
getLangOpts().getGC() == LangOptions::NonGC)
2288 builder.visitBlock(blockInfo);
2290 if (!builder.hasBitmapData())
2293 llvm::SmallVector<unsigned char, 32> buffer;
2294 llvm::Constant *
C = builder.buildBitmap(*
this, buffer);
2295 if (CGM.
getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
2296 printf(
"\n block variable layout for block: ");
2297 builder.dump(buffer);
2303void IvarLayoutBuilder::visitBlock(
const CGBlockInfo &blockInfo) {
2313 CharUnits lastFieldOffset;
2316 for (
const auto &CI :
blockDecl->captures()) {
2317 const VarDecl *variable = CI.getVariable();
2320 const CGBlockInfo::Capture &capture = blockInfo.
getCapture(variable);
2326 CharUnits fieldOffset = capture.
getOffset();
2330 if (fieldOffset < lastFieldOffset)
2331 IsDisordered =
true;
2332 lastFieldOffset = fieldOffset;
2336 IvarsInfo.push_back(IvarInfo(fieldOffset, 1));
2340 assert(!
type->isArrayType() &&
"array variable should not be caught");
2341 if (
const RecordType *record =
type->getAsCanonical<RecordType>()) {
2342 visitRecord(record, fieldOffset);
2351 IvarsInfo.push_back(IvarInfo(fieldOffset, 1));
2360CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
bool ByrefLayout) {
2376void CGObjCCommonMac::UpdateRunSkipBlockVars(
bool IsByref,
2378 CharUnits FieldOffset,
2379 CharUnits FieldSize) {
2382 RunSkipBlockVars.push_back(
2383 RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset, FieldSize));
2385 RunSkipBlockVars.push_back(
2386 RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset, FieldSize));
2388 RunSkipBlockVars.push_back(
2389 RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset, FieldSize));
2391 RunSkipBlockVars.push_back(
2392 RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset, FieldSize));
2394 RunSkipBlockVars.push_back(
2395 RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES, FieldOffset, FieldSize));
2398void CGObjCCommonMac::BuildRCRecordLayout(
const llvm::StructLayout *RecLayout,
2399 const RecordDecl *RD,
2400 ArrayRef<const FieldDecl *> RecFields,
2401 CharUnits BytePos,
bool &HasUnion,
2403 bool IsUnion = (RD && RD->
isUnion());
2405 const FieldDecl *MaxField =
nullptr;
2406 const FieldDecl *LastFieldBitfieldOrUnnamed =
nullptr;
2410 if (RecFields.empty())
2414 for (
unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2415 const FieldDecl *
Field = RecFields[i];
2419 CharUnits FieldOffset =
2423 if (!
Field->getIdentifier() ||
Field->isBitField()) {
2424 LastFieldBitfieldOrUnnamed =
Field;
2425 LastBitfieldOrUnnamedOffset = FieldOffset;
2429 LastFieldBitfieldOrUnnamed =
nullptr;
2430 QualType FQT =
Field->getType();
2436 BytePos + FieldOffset, HasUnion);
2442 uint64_t ElCount = CArray->getZExtSize();
2443 assert(CArray &&
"only array with known element size is supported");
2444 FQT = CArray->getElementType();
2447 ElCount *= CArray->getZExtSize();
2448 FQT = CArray->getElementType();
2451 int OldIndex = RunSkipBlockVars.size() - 1;
2453 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset, HasUnion);
2458 for (
int FirstIndex = RunSkipBlockVars.size() - 1; ElIx < ElCount;
2461 for (
int i = OldIndex + 1; i <= FirstIndex; ++i)
2462 RunSkipBlockVars.push_back(
2463 RUN_SKIP(RunSkipBlockVars[i].opcode,
2464 RunSkipBlockVars[i].block_var_bytepos + Size * ElIx,
2465 RunSkipBlockVars[i].block_var_size));
2472 CharUnits UnionIvarSize = FieldSize;
2473 if (UnionIvarSize > MaxUnionSize) {
2474 MaxUnionSize = UnionIvarSize;
2476 MaxFieldOffset = FieldOffset;
2479 UpdateRunSkipBlockVars(
false, getBlockCaptureLifetime(FQT, ByrefLayout),
2480 BytePos + FieldOffset, FieldSize);
2484 if (LastFieldBitfieldOrUnnamed) {
2485 if (LastFieldBitfieldOrUnnamed->
isBitField()) {
2488 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
2489 ((BitFieldSize % ByteSizeInBits) != 0);
2491 Size += LastBitfieldOrUnnamedOffset;
2492 UpdateRunSkipBlockVars(
2494 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->
getType(),
2496 BytePos + LastBitfieldOrUnnamedOffset, Size);
2499 "Expected unnamed");
2502 LastFieldBitfieldOrUnnamed->
getType());
2503 UpdateRunSkipBlockVars(
2505 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->
getType(),
2507 BytePos + LastBitfieldOrUnnamedOffset, FieldSize);
2512 UpdateRunSkipBlockVars(
2513 false, getBlockCaptureLifetime(MaxField->
getType(), ByrefLayout),
2514 BytePos + MaxFieldOffset, MaxUnionSize);
2517void CGObjCCommonMac::BuildRCBlockVarRecordLayout(
const RecordType *RT,
2521 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();
2522 SmallVector<const FieldDecl *, 16> Fields(RD->
fields());
2524 const llvm::StructLayout *RecLayout =
2527 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
2539uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2540 SmallVectorImpl<unsigned char> &Layout) {
2542 if (Layout.size() <= 3) {
2543 unsigned size = Layout.size();
2544 unsigned strong_word_count = 0, byref_word_count = 0, weak_word_count = 0;
2546 enum BLOCK_LAYOUT_OPCODE opcode;
2550 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2551 if (opcode == BLOCK_LAYOUT_STRONG)
2552 strong_word_count = (inst & 0xF) + 1;
2556 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2557 if (opcode == BLOCK_LAYOUT_BYREF)
2558 byref_word_count = (inst & 0xF) + 1;
2562 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2563 if (opcode == BLOCK_LAYOUT_WEAK)
2564 weak_word_count = (inst & 0xF) + 1;
2571 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2572 if (opcode == BLOCK_LAYOUT_STRONG) {
2573 strong_word_count = (inst & 0xF) + 1;
2575 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2576 if (opcode == BLOCK_LAYOUT_BYREF)
2577 byref_word_count = (inst & 0xF) + 1;
2578 else if (opcode == BLOCK_LAYOUT_WEAK)
2579 weak_word_count = (inst & 0xF) + 1;
2582 }
else if (opcode == BLOCK_LAYOUT_BYREF) {
2583 byref_word_count = (inst & 0xF) + 1;
2585 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2586 if (opcode == BLOCK_LAYOUT_WEAK)
2587 weak_word_count = (inst & 0xF) + 1;
2596 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2597 if (opcode == BLOCK_LAYOUT_STRONG)
2598 strong_word_count = (inst & 0xF) + 1;
2599 else if (opcode == BLOCK_LAYOUT_BYREF)
2600 byref_word_count = (inst & 0xF) + 1;
2601 else if (opcode == BLOCK_LAYOUT_WEAK)
2602 weak_word_count = (inst & 0xF) + 1;
2614 if (strong_word_count == 16 || byref_word_count == 16 ||
2615 weak_word_count == 16)
2618 unsigned count = (strong_word_count != 0) + (byref_word_count != 0) +
2619 (weak_word_count != 0);
2621 if (size == count) {
2622 if (strong_word_count)
2623 Result = strong_word_count;
2625 if (byref_word_count)
2626 Result += byref_word_count;
2628 if (weak_word_count)
2629 Result += weak_word_count;
2635llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(
bool ComputeByrefLayout) {
2636 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2637 if (RunSkipBlockVars.empty())
2641 unsigned WordSizeInBytes = WordSizeInBits / ByteSizeInBits;
2645 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2646 SmallVector<unsigned char, 16> Layout;
2648 unsigned size = RunSkipBlockVars.size();
2649 for (
unsigned i = 0; i < size; i++) {
2650 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2651 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2652 CharUnits end_byte_pos = start_byte_pos;
2655 if (opcode == RunSkipBlockVars[j].opcode) {
2656 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2661 CharUnits size_in_bytes =
2662 end_byte_pos - start_byte_pos + RunSkipBlockVars[j - 1].block_var_size;
2664 CharUnits gap = RunSkipBlockVars[j].block_var_bytepos -
2665 RunSkipBlockVars[j - 1].block_var_bytepos -
2666 RunSkipBlockVars[j - 1].block_var_size;
2667 size_in_bytes += gap;
2670 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2671 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2672 size_in_bytes -= residue_in_bytes;
2673 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2676 unsigned size_in_words = size_in_bytes.
getQuantity() / WordSizeInBytes;
2677 while (size_in_words >= 16) {
2680 unsigned char inst = (opcode << 4) | 0xf;
2681 Layout.push_back(inst);
2682 size_in_words -= 16;
2684 if (size_in_words > 0) {
2687 unsigned char inst = (opcode << 4) | (size_in_words - 1);
2688 Layout.push_back(inst);
2691 unsigned char inst = (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) |
2693 Layout.push_back(inst);
2697 while (!Layout.empty()) {
2698 unsigned char inst = Layout.back();
2699 enum BLOCK_LAYOUT_OPCODE opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2700 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES ||
2701 opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2711 if (ComputeByrefLayout)
2712 printf(
"\n Inline BYREF variable layout: ");
2714 printf(
"\n Inline block variable layout: ");
2716 if (
auto numStrong = (
Result & 0xF00) >> 8)
2717 printf(
", BL_STRONG:%d", (
int)numStrong);
2718 if (
auto numByref = (
Result & 0x0F0) >> 4)
2719 printf(
", BL_BYREF:%d", (
int)numByref);
2720 if (
auto numWeak = (
Result & 0x00F) >> 0)
2721 printf(
", BL_WEAK:%d", (
int)numWeak);
2722 printf(
", BL_OPERATOR:0\n");
2727 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2728 Layout.push_back(inst);
2730 for (
unsigned char C : Layout)
2734 if (ComputeByrefLayout)
2735 printf(
"\n Byref variable layout: ");
2737 printf(
"\n Block variable layout: ");
2738 for (
unsigned i = 0, e = BitMap.size(); i != e; i++) {
2739 unsigned char inst = BitMap[i];
2740 enum BLOCK_LAYOUT_OPCODE opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2743 case BLOCK_LAYOUT_OPERATOR:
2747 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2748 printf(
"BL_NON_OBJECT_BYTES:");
2750 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2751 printf(
"BL_NON_OBJECT_WORD:");
2753 case BLOCK_LAYOUT_STRONG:
2756 case BLOCK_LAYOUT_BYREF:
2759 case BLOCK_LAYOUT_WEAK:
2762 case BLOCK_LAYOUT_UNRETAINED:
2763 printf(
"BL_UNRETAINED:");
2768 printf(
"%d", (inst & 0xf) + delta);
2776 auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
2784 bool HasCopyDisposeHelpers) {
2786 for (
const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) {
2787 if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) {
2791 }
else if (HasCopyDisposeHelpers) {
2799 case CGObjCCommonMac::BLOCK_LAYOUT_STRONG:
2802 case CGObjCCommonMac::BLOCK_LAYOUT_BYREF:
2805 case CGObjCCommonMac::BLOCK_LAYOUT_WEAK:
2812 Str += llvm::to_string(R.block_var_bytepos.getQuantity());
2813 Str +=
"l" + llvm::to_string(R.block_var_size.getQuantity());
2818void CGObjCCommonMac::fillRunSkipBlockVars(CodeGenModule &CGM,
2819 const CGBlockInfo &blockInfo) {
2820 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
2822 RunSkipBlockVars.clear();
2823 bool hasUnion =
false;
2827 unsigned WordSizeInBytes = WordSizeInBits / ByteSizeInBits;
2832 const llvm::StructLayout *layout =
2842 for (
const auto &CI :
blockDecl->captures()) {
2843 const VarDecl *variable = CI.getVariable();
2846 const CGBlockInfo::Capture &capture = blockInfo.
getCapture(variable);
2852 CharUnits fieldOffset =
2855 assert(!
type->isArrayType() &&
"array variable should not be caught");
2857 if (
const auto *record =
type->getAsCanonical<RecordType>()) {
2858 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2861 CharUnits fieldSize;
2866 UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(
type,
false),
2867 fieldOffset, fieldSize);
2872CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
2873 const CGBlockInfo &blockInfo) {
2874 fillRunSkipBlockVars(CGM, blockInfo);
2875 return getBitmapBlockLayout(
false);
2878std::string CGObjCCommonMac::getRCBlockLayoutStr(CodeGenModule &CGM,
2879 const CGBlockInfo &blockInfo) {
2880 fillRunSkipBlockVars(CGM, blockInfo);
2884llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
2886 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
2887 assert(!
T->
isArrayType() &&
"__block array variable should not be caught");
2888 CharUnits fieldOffset;
2889 RunSkipBlockVars.clear();
2890 bool hasUnion =
false;
2892 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion,
2894 llvm::Constant *
Result = getBitmapBlockLayout(
true);
2899 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2903llvm::Value *CGObjCMac::GenerateProtocolRef(CodeGenFunction &CGF,
2904 const ObjCProtocolDecl *PD) {
2909 return GetProtocolRef(PD);
2912void CGObjCCommonMac::GenerateProtocol(
const ObjCProtocolDecl *PD) {
2921 GetOrEmitProtocol(PD);
2924llvm::Constant *CGObjCCommonMac::GetProtocolRef(
const ObjCProtocolDecl *PD) {
2926 return GetOrEmitProtocol(PD);
2928 return GetOrEmitProtocolRef(PD);
2932CGObjCCommonMac::EmitClassRefViaRuntime(CodeGenFunction &CGF,
2933 const ObjCInterfaceDecl *ID,
2934 ObjCCommonTypesHelper &ObjCTypes) {
2935 llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn();
2937 llvm::Value *className = CGF.
CGM
2939 ID->getObjCRuntimeNameAsString()))
2942 className = CGF.
Builder.CreateBitCast(
2944 llvm::CallInst *call = CGF.
Builder.CreateCall(lookUpClassFn, className);
2945 call->setDoesNotThrow();
2961llvm::Constant *CGObjCMac::GetOrEmitProtocol(
const ObjCProtocolDecl *PD) {
2962 llvm::GlobalVariable *Entry = Protocols[PD->
getIdentifier()];
2965 if (Entry && Entry->hasInitializer())
2977 auto methodLists = ProtocolMethodLists::get(PD);
2979 ConstantInitBuilder builder(CGM);
2980 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
2981 values.add(EmitProtocolExtension(PD, methodLists));
2983 values.add(EmitProtocolList(
"OBJC_PROTOCOL_REFS_" + PD->
getName(),
2985 values.add(methodLists.emitMethodList(
2986 this, PD, ProtocolMethodLists::RequiredInstanceMethods));
2987 values.add(methodLists.emitMethodList(
2988 this, PD, ProtocolMethodLists::RequiredClassMethods));
2992 assert(Entry->hasPrivateLinkage());
2993 values.finishAndSetAsInitializer(Entry);
2995 Entry = values.finishAndCreateGlobal(
2997 false, llvm::GlobalValue::PrivateLinkage);
2998 Entry->setSection(
"__OBJC,__protocol,regular,no_dead_strip");
3007llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD) {
3008 llvm::GlobalVariable *&Entry = Protocols[PD->
getIdentifier()];
3014 Entry =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ProtocolTy,
3015 false, llvm::GlobalValue::PrivateLinkage,
3016 nullptr,
"OBJC_PROTOCOL_" + PD->
getName());
3017 Entry->setSection(
"__OBJC,__protocol,regular,no_dead_strip");
3019 Entry->setAlignment(llvm::Align(4));
3036CGObjCMac::EmitProtocolExtension(
const ObjCProtocolDecl *PD,
3037 const ProtocolMethodLists &methodLists) {
3038 auto optInstanceMethods = methodLists.emitMethodList(
3039 this, PD, ProtocolMethodLists::OptionalInstanceMethods);
3040 auto optClassMethods = methodLists.emitMethodList(
3041 this, PD, ProtocolMethodLists::OptionalClassMethods);
3043 auto extendedMethodTypes = EmitProtocolMethodTypes(
3044 "OBJC_PROTOCOL_METHOD_TYPES_" + PD->
getName(),
3045 methodLists.emitExtendedTypesArray(
this), ObjCTypes);
3047 auto instanceProperties = EmitPropertyList(
3048 "OBJC_$_PROP_PROTO_LIST_" + PD->
getName(),
nullptr, PD, ObjCTypes,
false);
3049 auto classProperties =
3050 EmitPropertyList(
"OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->
getName(),
nullptr,
3051 PD, ObjCTypes,
true);
3054 if (optInstanceMethods->isNullValue() && optClassMethods->isNullValue() &&
3055 extendedMethodTypes->isNullValue() && instanceProperties->isNullValue() &&
3056 classProperties->isNullValue()) {
3057 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
3061 CGM.
getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
3063 ConstantInitBuilder builder(CGM);
3064 auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
3065 values.addInt(ObjCTypes.IntTy, size);
3066 values.add(optInstanceMethods);
3067 values.add(optClassMethods);
3068 values.add(instanceProperties);
3069 values.add(extendedMethodTypes);
3070 values.add(classProperties);
3073 return CreateMetadataVar(
"_OBJC_PROTOCOLEXT_" + PD->
getName(), values,
3085CGObjCMac::EmitProtocolList(Twine name,
3089 auto PDs = GetRuntimeProtocolList(begin, end);
3091 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
3093 ConstantInitBuilder builder(CGM);
3094 auto values = builder.beginStruct();
3097 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
3100 auto countSlot = values.addPlaceholder();
3102 auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
3103 for (
const auto *Proto : PDs)
3104 refsArray.add(GetProtocolRef(Proto));
3106 auto count = refsArray.size();
3109 refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
3111 refsArray.finishAndAddTo(values);
3112 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
3115 if (CGM.
getTriple().isOSBinFormatMachO())
3116 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3118 llvm::GlobalVariable *GV =
3119 CreateMetadataVar(name, values, section, CGM.
getPointerAlign(),
false);
3128 if (IsClassProperty != PD->isClassProperty())
3132 Properties.push_back(PD);
3135 for (
const auto *P : Proto->
protocols())
3151llvm::Constant *CGObjCCommonMac::EmitPropertyList(
3152 Twine Name,
const Decl *Container,
const ObjCContainerDecl *OCD,
3153 const ObjCCommonTypesHelper &ObjCTypes,
bool IsClassProperty) {
3154 if (IsClassProperty) {
3158 if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
3159 (Triple.isiOS() && Triple.isOSVersionLT(9)))
3160 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3163 SmallVector<const ObjCPropertyDecl *, 16> Properties;
3164 llvm::SmallPtrSet<const IdentifierInfo *, 16> PropertySet;
3166 if (
const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
3167 for (
const ObjCCategoryDecl *ClassExt : OID->known_extensions())
3168 for (
auto *PD : ClassExt->properties()) {
3169 if (IsClassProperty != PD->isClassProperty())
3171 if (PD->isDirectProperty())
3174 Properties.push_back(PD);
3178 if (IsClassProperty != PD->isClassProperty())
3184 if (PD->isDirectProperty())
3186 Properties.push_back(PD);
3189 if (
const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
3190 for (
const auto *P : OID->all_referenced_protocols())
3192 }
else if (
const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
3193 for (
const auto *P : CD->protocols())
3198 if (Properties.empty())
3199 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3201 unsigned propertySize =
3204 ConstantInitBuilder builder(CGM);
3205 auto values = builder.beginStruct();
3206 values.addInt(ObjCTypes.IntTy, propertySize);
3207 values.addInt(ObjCTypes.IntTy, Properties.size());
3208 auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
3209 for (
auto PD : Properties) {
3210 auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
3212 property.add(GetPropertyTypeString(PD, Container));
3213 property.finishAndAddTo(propertiesArray);
3215 propertiesArray.finishAndAddTo(values);
3218 if (CGM.
getTriple().isOSBinFormatMachO())
3219 Section = (ObjCABI == 2) ?
"__DATA, __objc_const"
3220 :
"__OBJC,__property,regular,no_dead_strip";
3222 llvm::GlobalVariable *GV =
3223 CreateMetadataVar(Name, values, Section, CGM.
getPointerAlign(),
true);
3227llvm::Constant *CGObjCCommonMac::EmitProtocolMethodTypes(
3228 Twine Name, ArrayRef<llvm::Constant *> MethodTypes,
3229 const ObjCCommonTypesHelper &ObjCTypes) {
3231 if (MethodTypes.empty())
3232 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
3234 llvm::ArrayType *AT =
3235 llvm::ArrayType::get(ObjCTypes.Int8PtrTy, MethodTypes.size());
3236 llvm::Constant *
Init = llvm::ConstantArray::get(AT, MethodTypes);
3239 if (CGM.
getTriple().isOSBinFormatMachO() && ObjCABI == 2)
3240 Section =
"__DATA, __objc_const";
3242 llvm::GlobalVariable *GV =
3259void CGObjCMac::GenerateCategory(
const ObjCCategoryImplDecl *OCD) {
3267 const ObjCCategoryDecl *Category =
3270 SmallString<256> ExtName;
3271 llvm::raw_svector_ostream(ExtName)
3274 ConstantInitBuilder Builder(CGM);
3275 auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
3277 enum { InstanceMethods, ClassMethods, NumMethodLists };
3278 SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
3279 for (
const auto *MD : OCD->
methods()) {
3280 if (!MD->isDirectMethod())
3281 Methods[unsigned(MD->isClassMethod())].push_back(MD);
3284 Values.add(GetClassName(OCD->
getName()));
3285 Values.add(GetClassName(
Interface->getObjCRuntimeNameAsString()));
3286 LazySymbols.insert(
Interface->getIdentifier());
3288 Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
3289 Methods[InstanceMethods]));
3290 Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
3291 Methods[ClassMethods]));
3293 Values.add(EmitProtocolList(
"OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
3294 Category->protocol_begin(),
3295 Category->protocol_end()));
3297 Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
3299 Values.addInt(ObjCTypes.IntTy, Size);
3303 Values.add(EmitPropertyList(
"_OBJC_$_PROP_LIST_" + ExtName.str(), OCD,
3304 Category, ObjCTypes,
false));
3305 Values.add(EmitPropertyList(
"_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), OCD,
3306 Category, ObjCTypes,
true));
3308 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3309 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3312 llvm::GlobalVariable *GV = CreateMetadataVar(
3313 "OBJC_CATEGORY_" + ExtName.str(), Values,
3314 "__OBJC,__category,regular,no_dead_strip", CGM.
getPointerAlign(),
true);
3315 DefinedCategories.push_back(GV);
3316 DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
3318 MethodDefinitions.clear();
3379 if (
auto *RD =
type->getAsRecordDecl()) {
3380 for (
auto *field : RD->
fields()) {
3399 ID->getClassInterface()->all_declared_ivar_begin();
3427void CGObjCMac::GenerateClass(
const ObjCImplementationDecl *ID) {
3428 IdentifierInfo *RuntimeName =
3430 DefinedSymbols.insert(RuntimeName);
3432 std::string ClassName =
ID->getNameAsString();
3435 const_cast<ObjCInterfaceDecl *
>(
ID->getClassInterface());
3436 llvm::Constant *Protocols =
3437 EmitProtocolList(
"OBJC_CLASS_PROTOCOLS_" +
ID->getName(),
3438 Interface->all_referenced_protocol_begin(),
3439 Interface->all_referenced_protocol_end());
3441 if (
ID->hasNonZeroConstructors() ||
ID->hasDestructors())
3444 bool hasMRCWeak =
false;
3459 enum { InstanceMethods, ClassMethods, NumMethodLists };
3460 SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
3461 for (
const auto *MD :
ID->methods()) {
3462 if (!MD->isDirectMethod())
3463 Methods[unsigned(MD->isClassMethod())].push_back(MD);
3466 for (
const auto *PID :
ID->property_impls()) {
3468 if (PID->getPropertyDecl()->isDirectProperty())
3470 if (ObjCMethodDecl *MD = PID->getGetterMethodDecl())
3471 if (GetMethodDefinition(MD))
3472 Methods[InstanceMethods].push_back(MD);
3473 if (ObjCMethodDecl *MD = PID->getSetterMethodDecl())
3474 if (GetMethodDefinition(MD))
3475 Methods[InstanceMethods].push_back(MD);
3479 ConstantInitBuilder builder(CGM);
3480 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3481 values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
3482 if (ObjCInterfaceDecl *Super =
Interface->getSuperClass()) {
3484 LazySymbols.insert(Super->getIdentifier());
3486 values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
3488 values.addNullPointer(ObjCTypes.ClassPtrTy);
3490 values.add(GetClassName(
ID->getObjCRuntimeNameAsString()));
3492 values.addInt(ObjCTypes.LongTy, 0);
3493 values.addInt(ObjCTypes.LongTy, Flags);
3494 values.addInt(ObjCTypes.LongTy,
Size.getQuantity());
3495 values.add(EmitIvarList(ID,
false));
3496 values.add(emitMethodList(
ID->getName(), MethodListType::InstanceMethods,
3497 Methods[InstanceMethods]));
3499 values.addNullPointer(ObjCTypes.CachePtrTy);
3500 values.add(Protocols);
3502 values.add(EmitClassExtension(ID, Size, hasMRCWeak,
3505 std::string Name(
"OBJC_CLASS_");
3507 const char *Section =
"__OBJC,__class,regular,no_dead_strip";
3509 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3511 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3512 "Forward metaclass reference has incorrect type.");
3513 values.finishAndSetAsInitializer(GV);
3514 GV->setSection(Section);
3518 GV = CreateMetadataVar(Name, values, Section, CGM.
getPointerAlign(),
true);
3519 DefinedClasses.push_back(GV);
3520 ImplementedClasses.push_back(
Interface);
3522 MethodDefinitions.clear();
3526CGObjCMac::EmitMetaClass(
const ObjCImplementationDecl *ID,
3527 llvm::Constant *Protocols,
3528 ArrayRef<const ObjCMethodDecl *> Methods) {
3535 ConstantInitBuilder builder(CGM);
3536 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3538 const ObjCInterfaceDecl *Root =
ID->getClassInterface();
3539 while (
const ObjCInterfaceDecl *Super = Root->
getSuperClass())
3545 if (ObjCInterfaceDecl *Super =
ID->getClassInterface()->getSuperClass()) {
3546 values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
3548 values.addNullPointer(ObjCTypes.ClassPtrTy);
3550 values.add(GetClassName(
ID->getObjCRuntimeNameAsString()));
3552 values.addInt(ObjCTypes.LongTy, 0);
3553 values.addInt(ObjCTypes.LongTy, Flags);
3554 values.addInt(ObjCTypes.LongTy, Size);
3555 values.add(EmitIvarList(ID,
true));
3557 emitMethodList(
ID->getName(), MethodListType::ClassMethods, Methods));
3559 values.addNullPointer(ObjCTypes.CachePtrTy);
3560 values.add(Protocols);
3562 values.addNullPointer(ObjCTypes.Int8PtrTy);
3567 std::string Name(
"OBJC_METACLASS_");
3568 Name +=
ID->getName();
3571 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3573 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3574 "Forward metaclass reference has incorrect type.");
3575 values.finishAndSetAsInitializer(GV);
3579 llvm::GlobalValue::PrivateLinkage);
3581 GV->setSection(
"__OBJC,__meta_class,regular,no_dead_strip");
3587llvm::Constant *CGObjCMac::EmitMetaClassRef(
const ObjCInterfaceDecl *ID) {
3588 std::string Name =
"OBJC_METACLASS_" +
ID->getNameAsString();
3598 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3600 GV =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ClassTy,
false,
3601 llvm::GlobalValue::PrivateLinkage,
nullptr,
3604 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3605 "Forward metaclass reference has incorrect type.");
3609llvm::Value *CGObjCMac::EmitSuperClassRef(
const ObjCInterfaceDecl *ID) {
3610 std::string Name =
"OBJC_CLASS_" +
ID->getNameAsString();
3611 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3614 GV =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ClassTy,
false,
3615 llvm::GlobalValue::PrivateLinkage,
nullptr,
3618 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3619 "Forward class metadata reference has incorrect type.");
3634llvm::Constant *CGObjCMac::EmitClassExtension(
const ObjCImplementationDecl *ID,
3635 CharUnits InstanceSize,
3639 llvm::Constant *layout;
3641 layout = llvm::ConstantPointerNull::get(CGM.
Int8PtrTy);
3648 llvm::Constant *propertyList =
3649 EmitPropertyList((isMetaclass ? Twine(
"_OBJC_$_CLASS_PROP_LIST_")
3650 : Twine(
"_OBJC_$_PROP_LIST_")) +
3652 ID,
ID->getClassInterface(), ObjCTypes, isMetaclass);
3655 if (layout->isNullValue() && propertyList->isNullValue()) {
3656 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
3660 CGM.
getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
3662 ConstantInitBuilder builder(CGM);
3663 auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
3664 values.addInt(ObjCTypes.IntTy, size);
3666 values.add(propertyList);
3668 return CreateMetadataVar(
"OBJC_CLASSEXT_" +
ID->getName(), values,
3669 "__OBJC,__class_ext,regular,no_dead_strip",
3685llvm::Constant *CGObjCMac::EmitIvarList(
const ObjCImplementationDecl *ID,
3693 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
3695 const ObjCInterfaceDecl *OID =
ID->getClassInterface();
3697 ConstantInitBuilder builder(CGM);
3698 auto ivarList = builder.beginStruct();
3699 auto countSlot = ivarList.addPlaceholder();
3700 auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
3705 if (!IVD->getDeclName())
3708 auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
3709 ivar.add(GetMethodVarName(IVD->getIdentifier()));
3710 ivar.add(GetMethodVarType(IVD));
3711 ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
3712 ivar.finishAndAddTo(ivars);
3716 auto count = ivars.size();
3720 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
3723 ivars.finishAndAddTo(ivarList);
3724 ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
3726 llvm::GlobalVariable *GV;
3727 GV = CreateMetadataVar(
"OBJC_INSTANCE_VARIABLES_" +
ID->getName(), ivarList,
3728 "__OBJC,__instance_vars,regular,no_dead_strip",
3739void CGObjCMac::emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
3740 const ObjCMethodDecl *MD) {
3741 auto description = builder.
beginStruct(ObjCTypes.MethodDescriptionTy);
3742 description.add(GetMethodVarName(MD->
getSelector()));
3743 description.add(GetMethodVarType(MD));
3744 description.finishAndAddTo(builder);
3754void CGObjCMac::emitMethodConstant(ConstantArrayBuilder &builder,
3755 const ObjCMethodDecl *MD) {
3756 llvm::Function *fn = GetMethodDefinition(MD);
3757 assert(fn &&
"no definition registered for method");
3759 auto method = builder.
beginStruct(ObjCTypes.MethodTy);
3761 method.add(GetMethodVarType(MD));
3763 method.finishAndAddTo(builder);
3780CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
3781 ArrayRef<const ObjCMethodDecl *> methods) {
3784 bool forProtocol =
false;
3786 case MethodListType::CategoryInstanceMethods:
3787 prefix =
"OBJC_CATEGORY_INSTANCE_METHODS_";
3788 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3789 forProtocol =
false;
3791 case MethodListType::CategoryClassMethods:
3792 prefix =
"OBJC_CATEGORY_CLASS_METHODS_";
3793 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3794 forProtocol =
false;
3796 case MethodListType::InstanceMethods:
3797 prefix =
"OBJC_INSTANCE_METHODS_";
3798 section =
"__OBJC,__inst_meth,regular,no_dead_strip";
3799 forProtocol =
false;
3801 case MethodListType::ClassMethods:
3802 prefix =
"OBJC_CLASS_METHODS_";
3803 section =
"__OBJC,__cls_meth,regular,no_dead_strip";
3804 forProtocol =
false;
3806 case MethodListType::ProtocolInstanceMethods:
3807 prefix =
"OBJC_PROTOCOL_INSTANCE_METHODS_";
3808 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3811 case MethodListType::ProtocolClassMethods:
3812 prefix =
"OBJC_PROTOCOL_CLASS_METHODS_";
3813 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3816 case MethodListType::OptionalProtocolInstanceMethods:
3817 prefix =
"OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
3818 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3821 case MethodListType::OptionalProtocolClassMethods:
3822 prefix =
"OBJC_PROTOCOL_CLASS_METHODS_OPT_";
3823 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3829 if (methods.empty())
3830 return llvm::Constant::getNullValue(
3831 forProtocol ? ObjCTypes.MethodDescriptionListPtrTy
3832 : ObjCTypes.MethodListPtrTy);
3837 ConstantInitBuilder builder(CGM);
3839 values.addInt(ObjCTypes.IntTy, methods.size());
3840 auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
3841 for (
auto MD : methods) {
3842 emitMethodDescriptionConstant(methodArray, MD);
3844 methodArray.finishAndAddTo(values);
3846 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3852 ConstantInitBuilder builder(CGM);
3854 values.addNullPointer(ObjCTypes.Int8PtrTy);
3855 values.addInt(ObjCTypes.IntTy, methods.size());
3856 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
3857 for (
auto MD : methods) {
3859 emitMethodConstant(methodArray, MD);
3861 methodArray.finishAndAddTo(values);
3863 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3868llvm::Function *CGObjCCommonMac::GenerateMethod(
const ObjCMethodDecl *OMD,
3869 const ObjCContainerDecl *CD) {
3874 DirectMethodInfo &Info = GenerateDirectMethod(OMD, CD);
3875 Method = Info.Implementation;
3877 auto Name = getSymbolNameForMethod(OMD);
3879 CodeGenTypes &Types = CGM.
getTypes();
3880 llvm::FunctionType *MethodTy =
3882 Method = llvm::Function::Create(
3883 MethodTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3886 MethodDefinitions.insert(std::make_pair(OMD,
Method));
3891CGObjCCommonMac::DirectMethodInfo &
3892CGObjCCommonMac::GenerateDirectMethod(
const ObjCMethodDecl *OMD,
3893 const ObjCContainerDecl *CD) {
3895 auto I = DirectMethodDefinitions.find(COMD);
3896 llvm::Function *OldFn =
nullptr, *
Fn =
nullptr;
3898 if (I != DirectMethodDefinitions.end()) {
3910 OldFn = I->second.Implementation;
3913 CodeGenTypes &Types = CGM.
getTypes();
3914 llvm::FunctionType *MethodTy =
3918 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
3920 Fn->takeName(OldFn);
3921 OldFn->replaceAllUsesWith(Fn);
3922 OldFn->eraseFromParent();
3925 I->second.Implementation =
Fn;
3928 auto Name = getSymbolNameForMethod(OMD,
false);
3930 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
3932 auto [It, inserted] = DirectMethodDefinitions.insert(
3933 std::make_pair(COMD, DirectMethodInfo(Fn)));
3943CGObjCCommonMac::GenerateClassRealization(CodeGenFunction &CGF,
3944 llvm::Value *classObject,
3945 const ObjCInterfaceDecl *OID) {
3952 RValue result = GeneratePossiblySpecializedMessageSend(
3953 CGF, ReturnValueSlot(), ResultType, SelfSel, classObject, Args, OID,
3959void CGObjCCommonMac::GenerateDirectMethodsPreconditionCheck(
3960 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
3961 const ObjCContainerDecl *CD) {
3963 bool ReceiverCanBeNull =
true;
3965 auto selfValue = Builder.CreateLoad(selfAddr);
3980 "GenerateDirectMethod() should be called with the Class Interface");
3991 llvm::Value *realizedClass = GenerateClassRealization(CGF, selfValue, OID);
3992 Builder.CreateStore(realizedClass, selfAddr);
3997 ReceiverCanBeNull = isWeakLinkedClass(OID);
4001 if (ReceiverCanBeNull) {
4002 llvm::BasicBlock *SelfIsNilBlock =
4004 llvm::BasicBlock *ContBlock =
4009 auto Zero = llvm::ConstantPointerNull::get(selfTy);
4012 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue,
Zero), SelfIsNilBlock,
4013 ContBlock, MDHelper.createUnlikelyBranchWeights());
4019 Builder.SetInsertPoint(SelfIsNilBlock);
4020 if (!retTy->isVoidType()) {
4028 Builder.SetInsertPoint(ContBlock);
4032void CGObjCCommonMac::GenerateDirectMethodPrologue(
4033 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
4034 const ObjCContainerDecl *CD) {
4036 GenerateDirectMethodsPreconditionCheck(CGF, Fn, OMD, CD);
4045 Builder.CreateStore(GetSelector(CGF, OMD),
4050llvm::GlobalVariable *
4051CGObjCCommonMac::CreateMetadataVar(Twine Name, ConstantStructBuilder &
Init,
4052 StringRef Section, CharUnits Align,
4054 llvm::GlobalValue::LinkageTypes
LT =
4056 llvm::GlobalVariable *GV =
4057 Init.finishAndCreateGlobal(Name, Align,
false, LT);
4058 if (!Section.empty())
4059 GV->setSection(Section);
4065llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
4066 llvm::Constant *
Init,
4070 llvm::Type *Ty =
Init->getType();
4071 llvm::GlobalValue::LinkageTypes
LT =
4073 llvm::GlobalVariable *GV =
4074 new llvm::GlobalVariable(CGM.
getModule(), Ty,
false, LT,
Init, Name);
4075 if (!Section.empty())
4076 GV->setSection(Section);
4083llvm::GlobalVariable *
4084CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType
Type,
4085 bool ForceNonFragileABI,
4086 bool NullTerminate) {
4089 case ObjCLabelType::ClassName:
4090 Label =
"OBJC_CLASS_NAME_";
4092 case ObjCLabelType::MethodVarName:
4093 Label =
"OBJC_METH_VAR_NAME_";
4095 case ObjCLabelType::MethodVarType:
4096 Label =
"OBJC_METH_VAR_TYPE_";
4098 case ObjCLabelType::PropertyName:
4099 Label =
"OBJC_PROP_NAME_ATTR_";
4101 case ObjCLabelType::LayoutBitMap:
4102 Label =
"OBJC_LAYOUT_BITMAP_";
4106 bool NonFragile = ForceNonFragileABI || isNonFragileABI();
4110 case ObjCLabelType::ClassName:
4111 Section = NonFragile ?
"__TEXT,__objc_classname,cstring_literals"
4112 :
"__TEXT,__cstring,cstring_literals";
4114 case ObjCLabelType::MethodVarName:
4115 Section = NonFragile ?
"__TEXT,__objc_methname,cstring_literals"
4116 :
"__TEXT,__cstring,cstring_literals";
4118 case ObjCLabelType::MethodVarType:
4119 Section = NonFragile ?
"__TEXT,__objc_methtype,cstring_literals"
4120 :
"__TEXT,__cstring,cstring_literals";
4122 case ObjCLabelType::PropertyName:
4123 Section = NonFragile ?
"__TEXT,__objc_methname,cstring_literals"
4124 :
"__TEXT,__cstring,cstring_literals";
4126 case ObjCLabelType::LayoutBitMap:
4127 Section =
"__TEXT,__cstring,cstring_literals";
4131 llvm::Constant *
Value =
4132 llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
4133 llvm::GlobalVariable *GV =
new llvm::GlobalVariable(
4135 true, llvm::GlobalValue::PrivateLinkage,
Value, Label);
4136 if (CGM.
getTriple().isOSBinFormatMachO())
4137 GV->setSection(Section);
4138 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4145llvm::Function *CGObjCMac::ModuleInitFunction() {
4151llvm::FunctionCallee CGObjCMac::GetPropertyGetFunction() {
4152 return ObjCTypes.getGetPropertyFn();
4155llvm::FunctionCallee CGObjCMac::GetPropertySetFunction() {
4156 return ObjCTypes.getSetPropertyFn();
4159llvm::FunctionCallee CGObjCMac::GetOptimizedPropertySetFunction(
bool atomic,
4161 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
4164llvm::FunctionCallee CGObjCMac::GetGetStructFunction() {
4165 return ObjCTypes.getCopyStructFn();
4168llvm::FunctionCallee CGObjCMac::GetSetStructFunction() {
4169 return ObjCTypes.getCopyStructFn();
4172llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectGetFunction() {
4173 return ObjCTypes.getCppAtomicObjectFunction();
4176llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectSetFunction() {
4177 return ObjCTypes.getCppAtomicObjectFunction();
4180llvm::FunctionCallee CGObjCMac::EnumerationMutationFunction() {
4181 return ObjCTypes.getEnumerationMutationFn();
4184void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF,
const ObjCAtTryStmt &S) {
4185 return EmitTryOrSynchronizedStmt(CGF, S);
4188void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
4189 const ObjCAtSynchronizedStmt &S) {
4190 return EmitTryOrSynchronizedStmt(CGF, S);
4194struct PerformFragileFinally final : EHScopeStack::Cleanup {
4196 Address SyncArgSlot;
4197 Address CallTryExitVar;
4198 Address ExceptionData;
4199 ObjCTypesHelper &ObjCTypes;
4200 PerformFragileFinally(
const Stmt *S, Address SyncArgSlot,
4201 Address CallTryExitVar, Address ExceptionData,
4202 ObjCTypesHelper *ObjCTypes)
4203 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
4204 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
4206 void Emit(CodeGenFunction &CGF, Flags flags)
override {
4209 llvm::BasicBlock *FinallyCallExit =
4211 llvm::BasicBlock *FinallyNoCallExit =
4214 FinallyCallExit, FinallyNoCallExit);
4223 if (
const ObjCAtFinallyStmt *FinallyStmt =
4226 if (flags.isForEHCleanup())
4231 llvm::Value *CurCleanupDest =
4234 CGF.
EmitStmt(FinallyStmt->getFinallyBody());
4253class FragileHazards {
4254 CodeGenFunction &CGF;
4255 SmallVector<llvm::Value *, 20> Locals;
4256 llvm::DenseSet<llvm::BasicBlock *> BlocksBeforeTry;
4258 llvm::InlineAsm *ReadHazard;
4259 llvm::InlineAsm *WriteHazard;
4261 llvm::FunctionType *GetAsmFnType();
4263 void collectLocals();
4264 void emitReadHazard(CGBuilderTy &Builder);
4267 FragileHazards(CodeGenFunction &CGF);
4269 void emitWriteHazard();
4270 void emitHazardsInNewBlocks();
4279FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
4286 for (llvm::BasicBlock &BB : *CGF.
CurFn)
4287 BlocksBeforeTry.insert(&BB);
4289 llvm::FunctionType *AsmFnTy = GetAsmFnType();
4297 std::string Constraint;
4298 for (
unsigned I = 0, E = Locals.size(); I != E; ++I) {
4304 ReadHazard = llvm::InlineAsm::get(AsmFnTy,
"", Constraint,
true,
false);
4312 std::string Constraint;
4313 for (
unsigned I = 0, E = Locals.size(); I != E; ++I) {
4316 Constraint +=
"=*m";
4319 WriteHazard = llvm::InlineAsm::get(AsmFnTy,
"", Constraint,
true,
false);
4324void FragileHazards::emitWriteHazard() {
4329 for (
auto Pair : llvm::enumerate(Locals))
4332 llvm::Attribute::get(
4337void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
4338 assert(!Locals.empty());
4339 llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
4340 call->setDoesNotThrow();
4342 for (
auto Pair : llvm::enumerate(Locals))
4345 llvm::Attribute::get(
4346 Builder.getContext(), llvm::Attribute::ElementType,
4352void FragileHazards::emitHazardsInNewBlocks() {
4359 for (llvm::BasicBlock &BB : *CGF.
CurFn) {
4360 if (BlocksBeforeTry.count(&BB))
4364 for (llvm::BasicBlock::iterator BI = BB.begin(), BE = BB.end(); BI != BE;
4366 llvm::Instruction &I = *BI;
4385 Builder.SetInsertPoint(&BB, BI);
4386 emitReadHazard(Builder);
4393 if (llvm::Value *Ptr =
V.getBasePointer())
4397void FragileHazards::collectLocals() {
4399 llvm::DenseSet<llvm::Value *> AllocasToIgnore;
4405 llvm::BasicBlock &Entry = CGF.
CurFn->getEntryBlock();
4406 for (llvm::Instruction &I : Entry)
4408 Locals.push_back(&I);
4411llvm::FunctionType *FragileHazards::GetAsmFnType() {
4412 SmallVector<llvm::Type *, 16> tys(Locals.size());
4413 for (
unsigned i = 0, e = Locals.size(); i != e; ++i)
4414 tys[i] = Locals[i]->getType();
4415 return llvm::FunctionType::get(CGF.
VoidTy, tys,
false);
4526void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
4532 CodeGenFunction::JumpDest FinallyEnd =
4537 CodeGenFunction::JumpDest FinallyRethrow =
4547 llvm::Value *SyncArg =
4549 SyncArg = CGF.
Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
4560 ObjCTypes.ExceptionDataTy, CGF.
getPointerAlign(),
"exceptiondata.ptr");
4566 FragileHazards Hazards(CGF);
4585 SyncArgSlot, CallTryExitVar,
4586 ExceptionData, &ObjCTypes);
4592 ExceptionData.emitRawPointer(CGF));
4595 llvm::Constant *
Zero = llvm::ConstantInt::get(CGF.
Builder.getInt32Ty(), 0);
4598 ObjCTypes.ExceptionDataTy, ExceptionData.emitRawPointer(CGF), GEPIndexes,
4601 ObjCTypes.getSetJmpFn(), SetJmpBuffer,
"setjmp_result");
4602 SetJmpResult->setCanReturnTwice();
4608 llvm::Value *DidCatch =
4609 CGF.
Builder.CreateIsNotNull(SetJmpResult,
"did_catch_exception");
4610 CGF.
Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
4618 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.
Builder.saveAndClearIP();
4624 Hazards.emitWriteHazard();
4638 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF),
4649 llvm::BasicBlock *CatchBlock =
nullptr;
4650 llvm::BasicBlock *CatchHandler =
nullptr;
4661 ExceptionData.emitRawPointer(CGF));
4664 ObjCTypes.getSetJmpFn(), SetJmpBuffer,
"setjmp.result");
4665 SetJmpResult->setCanReturnTwice();
4667 llvm::Value *Threw =
4668 CGF.
Builder.CreateIsNotNull(SetJmpResult,
"did_catch_exception");
4672 CGF.
Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
4682 bool AllMatched =
false;
4683 for (
const ObjCAtCatchStmt *CatchStmt : AtTryStmt->
catch_stmts()) {
4684 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
4685 const ObjCObjectPointerType *OPT =
nullptr;
4691 OPT = CatchParam->
getType()->
getAs<ObjCObjectPointerType>();
4703 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4710 EmitInitOfCatchParam(CGF, Caught, CatchParam);
4713 CGF.
EmitStmt(CatchStmt->getCatchBody());
4716 CatchVarCleanups.ForceCleanup();
4722 assert(OPT &&
"Unexpected non-object pointer type in @catch");
4726 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
4727 assert(IDecl &&
"Catch parameter must have Objective-C type!");
4730 llvm::Value *
Class = EmitClassRef(CGF, IDecl);
4732 llvm::Value *matchArgs[] = {
Class, Caught};
4734 ObjCTypes.getExceptionMatchFn(), matchArgs,
"match");
4740 MatchedBlock, NextCatchBlock);
4747 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4753 llvm::Value *Tmp = CGF.
Builder.CreateBitCast(
4755 EmitInitOfCatchParam(CGF, Tmp, CatchParam);
4757 CGF.
EmitStmt(CatchStmt->getCatchBody());
4760 CatchVarCleanups.ForceCleanup();
4771 if (Caught->use_empty())
4772 Caught->eraseFromParent();
4788 assert(PropagatingExnVar.
isValid());
4790 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF),
4801 Hazards.emitHazardsInNewBlocks();
4804 CGF.
Builder.restoreIP(TryFallthroughIP);
4811 CGBuilderTy::InsertPoint SavedIP = CGF.
Builder.saveAndClearIP();
4815 llvm::Value *PropagatingExn;
4816 if (PropagatingExnVar.
isValid()) {
4822 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF));
4823 PropagatingExn = Caught;
4828 CGF.
Builder.CreateUnreachable();
4831 CGF.
Builder.restoreIP(SavedIP);
4834void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
4835 const ObjCAtThrowStmt &S,
4836 bool ClearInsertionPoint) {
4837 llvm::Value *ExceptionAsObject;
4842 CGF.
Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
4845 "Unexpected rethrow outside @catch block.");
4849 CGF.
EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
4850 ->setDoesNotReturn();
4851 CGF.
Builder.CreateUnreachable();
4854 if (ClearInsertionPoint)
4855 CGF.
Builder.ClearInsertionPoint();
4861llvm::Value *CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
4862 Address AddrWeakObj) {
4864 llvm::Value *AddrWeakObjVal = CGF.
Builder.CreateBitCast(
4867 ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal,
"weakread");
4868 read_weak = CGF.
Builder.CreateBitCast(read_weak, DestTy);
4875void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
4876 llvm::Value *src, Address dst) {
4877 llvm::Type *SrcTy = src->getType();
4880 assert(Size <= 8 && "does not support size > 8
");
4881 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4882 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4883 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4885 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4886 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4887 ObjCTypes.PtrObjectPtrTy);
4888 llvm::Value *args[] = {src, dstVal};
4889 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args,
4896void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
4897 llvm::Value *src, Address dst,
4899 llvm::Type *SrcTy = src->getType();
4900 if (!isa<llvm::PointerType>(SrcTy)) {
4901 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4902 assert(Size <= 8 && "does
not support size > 8
");
4903 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4904 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4905 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4907 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4908 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4909 ObjCTypes.PtrObjectPtrTy);
4910 llvm::Value *args[] = {src, dstVal};
4912 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), args,
4915 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), args,
4916 "threadlocalassign
");
4922void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
4923 llvm::Value *src, Address dst,
4924 llvm::Value *ivarOffset) {
4925 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset
is NULL");
4926 llvm::Type *SrcTy = src->getType();
4927 if (!isa<llvm::PointerType>(SrcTy)) {
4928 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4929 assert(Size <= 8 && "does
not support size > 8
");
4930 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4931 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4932 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4934 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4935 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4936 ObjCTypes.PtrObjectPtrTy);
4937 llvm::Value *args[] = {src, dstVal, ivarOffset};
4938 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
4944void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
4945 llvm::Value *src, Address dst) {
4946 llvm::Type *SrcTy = src->getType();
4947 if (!isa<llvm::PointerType>(SrcTy)) {
4948 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4949 assert(Size <= 8 && "does
not support size > 8
");
4950 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4951 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4952 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4954 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4955 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4956 ObjCTypes.PtrObjectPtrTy);
4957 llvm::Value *args[] = {src, dstVal};
4958 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args,
4962void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
4963 Address DestPtr, Address SrcPtr,
4964 llvm::Value *size) {
4965 llvm::Value *args[] = {DestPtr.emitRawPointer(CGF),
4966 SrcPtr.emitRawPointer(CGF), size};
4967 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
4972LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
4974 llvm::Value *BaseValue,
4975 const ObjCIvarDecl *Ivar,
4976 unsigned CVRQualifiers) {
4977 const ObjCInterfaceDecl *ID =
4978 ObjectTy->castAs<ObjCObjectType>()->getInterface();
4979 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4980 EmitIvarOffset(CGF, ID, Ivar));
4983llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
4984 const ObjCInterfaceDecl *Interface,
4985 const ObjCIvarDecl *Ivar) {
4986 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
4987 return llvm::ConstantInt::get(
4988 CGM.getTypes().ConvertType(CGM.getContext().LongTy), Offset);
4991/* *** Private Interface *** */
4993std::string CGObjCCommonMac::GetSectionName(StringRef Section,
4994 StringRef MachOAttributes) {
4995 switch (CGM.getTriple().getObjectFormat()) {
4996 case llvm::Triple::UnknownObjectFormat:
4997 llvm_unreachable("unexpected
object file format
");
4998 case llvm::Triple::MachO: {
4999 if (MachOAttributes.empty())
5000 return ("__DATA,
" + Section).str();
5001 return ("__DATA,
" + Section + ",
" + MachOAttributes).str();
5003 case llvm::Triple::ELF:
5004 assert(Section.starts_with("__
") && "expected the name to begin with __
");
5005 return Section.substr(2).str();
5006 case llvm::Triple::COFF:
5007 assert(Section.starts_with("__
") && "expected the name to begin with __
");
5008 return (".
" + Section.substr(2) + "$B
").str();
5009 case llvm::Triple::Wasm:
5010 case llvm::Triple::GOFF:
5011 case llvm::Triple::SPIRV:
5012 case llvm::Triple::XCOFF:
5013 case llvm::Triple::DXContainer:
5014 llvm::report_fatal_error(
5015 "Objective-
C support
is unimplemented
for object file format
");
5018 llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType
enum");
5030enum ImageInfoFlags {
5031 eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
5032 eImageInfo_GarbageCollected = (1 << 1),
5033 eImageInfo_GCOnly = (1 << 2),
5034 eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
5036 eImageInfo_SignedClassRO = (1 << 4), // Reused (was _CorrectedSynthesize)
5037 eImageInfo_ImageIsSimulated = (1 << 5),
5038 eImageInfo_ClassProperties = (1 << 6)
5042void CGObjCCommonMac::EmitImageInfo() {
5043 unsigned version = 0; // Version is unused?
5044 std::string Section =
5046 ? "__OBJC,__image_info,regular
"
5047 : GetSectionName("__objc_imageinfo
", "regular,no_dead_strip
");
5049 // Generate module-level named metadata to convey this information to the
5050 // linker and code-gen.
5051 llvm::Module &Mod = CGM.getModule();
5053 // Add the ObjC ABI version to the module flags.
5054 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Version
", ObjCABI);
5055 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Image Info Version
",
5057 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Image Info Section
",
5058 llvm::MDString::get(VMContext, Section));
5060 auto Int8Ty = llvm::Type::getInt8Ty(VMContext);
5061 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
5062 // Non-GC overrides those files which specify GC.
5063 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Garbage Collection
",
5064 llvm::ConstantInt::get(Int8Ty, 0));
5066 // Add the ObjC garbage collection value.
5068 llvm::Module::Error, "Objective-
C Garbage Collection
",
5069 llvm::ConstantInt::get(Int8Ty, (uint8_t)eImageInfo_GarbageCollected));
5071 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
5072 // Add the ObjC GC Only value.
5073 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C GC Only
",
5076 // Require that GC be specified and set to eImageInfo_GarbageCollected.
5077 llvm::Metadata *Ops[2] = {
5078 llvm::MDString::get(VMContext, "Objective-
C Garbage Collection
"),
5079 llvm::ConstantAsMetadata::get(
5080 llvm::ConstantInt::get(Int8Ty, eImageInfo_GarbageCollected))};
5081 Mod.addModuleFlag(llvm::Module::Require, "Objective-
C GC Only
",
5082 llvm::MDNode::get(VMContext, Ops));
5086 // Indicate whether we're compiling this to run on a simulator.
5087 if (CGM.getTarget().getTriple().isSimulatorEnvironment())
5088 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Is Simulated
",
5089 eImageInfo_ImageIsSimulated);
5091 // Indicate whether we are generating class properties.
5092 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Class Properties
",
5093 eImageInfo_ClassProperties);
5095 // Indicate whether we want enforcement of pointer signing for class_ro_t
5097 if (CGM.getLangOpts().PointerAuthObjcClassROPointers)
5098 Mod.addModuleFlag(llvm::Module::Error,
5099 "Objective-
C Enforce ClassRO
Pointer Signing
",
5100 eImageInfo_SignedClassRO);
5102 Mod.addModuleFlag(llvm::Module::Error,
5103 "Objective-
C Enforce ClassRO
Pointer Signing
",
5104 llvm::ConstantInt::get(Int8Ty, 0));
5107// struct objc_module {
5108// unsigned long version;
5109// unsigned long size;
5114// FIXME: Get from somewhere
5115static const int ModuleVersion = 7;
5117void CGObjCMac::EmitModuleInfo() {
5118 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
5120 ConstantInitBuilder builder(CGM);
5121 auto values = builder.beginStruct(ObjCTypes.ModuleTy);
5122 values.addInt(ObjCTypes.LongTy, ModuleVersion);
5123 values.addInt(ObjCTypes.LongTy, Size);
5124 // This used to be the filename, now it is unused. <rdr://4327263>
5125 values.add(GetClassName(StringRef("")));
5126 values.add(EmitModuleSymbols());
5127 CreateMetadataVar("OBJC_MODULES
", values,
5128 "__OBJC,__module_info,regular,no_dead_strip
",
5129 CGM.getPointerAlign(), true);
5132llvm::Constant *CGObjCMac::EmitModuleSymbols() {
5133 unsigned NumClasses = DefinedClasses.size();
5134 unsigned NumCategories = DefinedCategories.size();
5136 // Return null if no symbols were defined.
5137 if (!NumClasses && !NumCategories)
5138 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
5140 ConstantInitBuilder builder(CGM);
5141 auto values = builder.beginStruct();
5142 values.addInt(ObjCTypes.LongTy, 0);
5143 values.addNullPointer(ObjCTypes.SelectorPtrTy);
5144 values.addInt(ObjCTypes.ShortTy, NumClasses);
5145 values.addInt(ObjCTypes.ShortTy, NumCategories);
5147 // The runtime expects exactly the list of defined classes followed
5148 // by the list of defined categories, in a single array.
5149 auto array = values.beginArray(ObjCTypes.Int8PtrTy);
5150 for (unsigned i = 0; i < NumClasses; i++) {
5151 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
5153 if (ObjCImplementationDecl *IMP = ID->getImplementation())
5154 // We are implementing a weak imported interface. Give it external linkage
5155 if (ID->isWeakImported() && !IMP->isWeakImported())
5156 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
5158 array.add(DefinedClasses[i]);
5160 for (unsigned i = 0; i < NumCategories; i++)
5161 array.add(DefinedCategories[i]);
5163 array.finishAndAddTo(values);
5165 llvm::GlobalVariable *GV = CreateMetadataVar(
5166 "OBJC_SYMBOLS
", values, "__OBJC,__symbols,regular,no_dead_strip
",
5167 CGM.getPointerAlign(), true);
5171llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
5172 IdentifierInfo *II) {
5173 LazySymbols.insert(II);
5175 llvm::GlobalVariable *&Entry = ClassReferences[II];
5179 CreateMetadataVar("OBJC_CLASS_REFERENCES_
", GetClassName(II->getName()),
5180 "__OBJC,__cls_refs,literal_pointers,no_dead_strip
",
5181 CGM.getPointerAlign(), true);
5184 return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry,
5185 CGF.getPointerAlign());
5188llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
5189 const ObjCInterfaceDecl *ID) {
5190 // If the class has the objc_runtime_visible attribute, we need to
5191 // use the Objective-C runtime to get the class.
5192 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
5193 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
5195 IdentifierInfo *RuntimeName =
5196 &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
5197 return EmitClassRefFromId(CGF, RuntimeName);
5200llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
5201 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool
");
5202 return EmitClassRefFromId(CGF, II);
5205llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
5206 return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel));
5209ConstantAddress CGObjCMac::EmitSelectorAddr(Selector Sel) {
5210 CharUnits Align = CGM.getPointerAlign();
5212 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
5214 Entry = CreateMetadataVar(
5215 "OBJC_SELECTOR_REFERENCES_
", GetMethodVarName(Sel),
5216 "__OBJC,__message_refs,literal_pointers,no_dead_strip
", Align, true);
5217 Entry->setExternallyInitialized(true);
5220 return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align);
5223llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
5224 llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
5226 Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
5227 return getConstantGEP(VMContext, Entry, 0, 0);
5230llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
5231 return MethodDefinitions.lookup(MD);
5237CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
5238 const ObjCCommonTypesHelper &ObjCTypes) {
5239 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
5242void IvarLayoutBuilder::visitRecord(const RecordType *RT, CharUnits offset) {
5243 const RecordDecl *RD = RT->getDecl()->getDefinitionOrSelf();
5245 // If this is a union, remember that we had one, because it might mess
5246 // up the ordering of layout entries.
5248 IsDisordered = true;
5250 const ASTRecordLayout *recLayout = nullptr;
5251 visitAggregate(RD->field_begin(), RD->field_end(), offset,
5252 [&](const FieldDecl *field) -> CharUnits {
5254 recLayout = &CGM.getContext().getASTRecordLayout(RD);
5256 recLayout->getFieldOffset(field->getFieldIndex());
5257 return CGM.getContext().toCharUnitsFromBits(offsetInBits);
5261template <class Iterator, class GetOffsetFn>
5262void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
5263 CharUnits aggregateOffset,
5264 const GetOffsetFn &getOffset) {
5265 for (; begin != end; ++begin) {
5266 auto field = *begin;
5268 // Skip over bitfields.
5269 if (field->isBitField()) {
5273 // Compute the offset of the field within the aggregate.
5274 CharUnits fieldOffset = aggregateOffset + getOffset(field);
5276 visitField(field, fieldOffset);
5281void IvarLayoutBuilder::visitField(const FieldDecl *field,
5282 CharUnits fieldOffset) {
5283 QualType fieldType = field->getType();
5285 // Drill down into arrays.
5286 uint64_t numElts = 1;
5287 if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) {
5289 fieldType = arrayType->getElementType();
5291 // Unlike incomplete arrays, constant arrays can be nested.
5292 while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
5293 numElts *= arrayType->getZExtSize();
5294 fieldType = arrayType->getElementType();
5297 assert(!fieldType->isArrayType() && "ivar of non-constant array
type?
");
5299 // If we ended up with a zero-sized array, we've done what we can do within
5300 // the limits of this layout encoding.
5304 // Recurse if the base element type is a record type.
5305 if (const auto *recType = fieldType->getAsCanonical<RecordType>()) {
5306 size_t oldEnd = IvarsInfo.size();
5308 visitRecord(recType, fieldOffset);
5310 // If we have an array, replicate the first entry's layout information.
5311 auto numEltEntries = IvarsInfo.size() - oldEnd;
5312 if (numElts != 1 && numEltEntries != 0) {
5313 CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
5314 for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
5315 // Copy the last numEltEntries onto the end of the array, adjusting
5316 // each for the element size.
5317 for (size_t i = 0; i != numEltEntries; ++i) {
5318 auto firstEntry = IvarsInfo[oldEnd + i];
5319 IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
5320 firstEntry.SizeInWords));
5328 // Classify the element type.
5329 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
5331 // If it matches what we're looking for, add an entry.
5332 if ((ForStrongLayout && GCAttr == Qualifiers::Strong) ||
5333 (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
5334 assert(CGM.getContext().getTypeSizeInChars(fieldType) ==
5335 CGM.getPointerSize());
5336 IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
5344IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
5345 llvm::SmallVectorImpl<unsigned char> &buffer) {
5346 // The bitmap is a series of skip/scan instructions, aligned to word
5347 // boundaries. The skip is performed first.
5348 const unsigned char MaxNibble = 0xF;
5349 const unsigned char SkipMask = 0xF0, SkipShift = 4;
5350 const unsigned char ScanMask = 0x0F, ScanShift = 0;
5352 assert(!IvarsInfo.empty() && "generating bitmap
for no data
");
5354 // Sort the ivar info on byte position in case we encounterred a
5355 // union nested in the ivar list.
5357 // This isn't a stable sort, but our algorithm should handle it fine.
5358 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
5360 assert(llvm::is_sorted(IvarsInfo));
5362 assert(IvarsInfo.back().Offset < InstanceEnd);
5364 assert(buffer.empty());
5366 // Skip the next N words.
5367 auto skip = [&](unsigned numWords) {
5368 assert(numWords > 0);
5370 // Try to merge into the previous byte. Since scans happen second, we
5371 // can't do this if it includes a scan.
5372 if (!buffer.empty() && !(buffer.back() & ScanMask)) {
5373 unsigned lastSkip = buffer.back() >> SkipShift;
5374 if (lastSkip < MaxNibble) {
5375 unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
5376 numWords -= claimed;
5377 lastSkip += claimed;
5378 buffer.back() = (lastSkip << SkipShift);
5382 while (numWords >= MaxNibble) {
5383 buffer.push_back(MaxNibble << SkipShift);
5384 numWords -= MaxNibble;
5387 buffer.push_back(numWords << SkipShift);
5391 // Scan the next N words.
5392 auto scan = [&](unsigned numWords) {
5393 assert(numWords > 0);
5395 // Try to merge into the previous byte. Since scans happen second, we can
5396 // do this even if it includes a skip.
5397 if (!buffer.empty()) {
5398 unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
5399 if (lastScan < MaxNibble) {
5400 unsigned claimed = std::min(MaxNibble - lastScan, numWords);
5401 numWords -= claimed;
5402 lastScan += claimed;
5403 buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
5407 while (numWords >= MaxNibble) {
5408 buffer.push_back(MaxNibble << ScanShift);
5409 numWords -= MaxNibble;
5412 buffer.push_back(numWords << ScanShift);
5416 // One past the end of the last scan.
5417 unsigned endOfLastScanInWords = 0;
5418 const CharUnits WordSize = CGM.getPointerSize();
5420 // Consider all the scan requests.
5421 for (auto &request : IvarsInfo) {
5422 CharUnits beginOfScan = request.Offset - InstanceBegin;
5424 // Ignore scan requests that don't start at an even multiple of the
5425 // word size. We can't encode them.
5426 if (!beginOfScan.isMultipleOf(WordSize))
5429 // Ignore scan requests that start before the instance start.
5430 // This assumes that scans never span that boundary. The boundary
5431 // isn't the true start of the ivars, because in the fragile-ARC case
5432 // it's rounded up to word alignment, but the test above should leave
5433 // us ignoring that possibility.
5434 if (beginOfScan.isNegative()) {
5435 assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
5439 unsigned beginOfScanInWords = beginOfScan / WordSize;
5440 unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
5442 // If the scan starts some number of words after the last one ended,
5444 if (beginOfScanInWords > endOfLastScanInWords) {
5445 skip(beginOfScanInWords - endOfLastScanInWords);
5447 // Otherwise, start scanning where the last left off.
5449 beginOfScanInWords = endOfLastScanInWords;
5451 // If that leaves us with nothing to scan, ignore this request.
5452 if (beginOfScanInWords >= endOfScanInWords)
5456 // Scan to the end of the request.
5457 assert(beginOfScanInWords < endOfScanInWords);
5458 scan(endOfScanInWords - beginOfScanInWords);
5459 endOfLastScanInWords = endOfScanInWords;
5463 return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
5465 // For GC layouts, emit a skip to the end of the allocation so that we
5466 // have precise information about the entire thing. This isn't useful
5467 // or necessary for the ARC-style layout strings.
5468 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
5469 unsigned lastOffsetInWords =
5470 (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
5471 if (lastOffsetInWords > endOfLastScanInWords) {
5472 skip(lastOffsetInWords - endOfLastScanInWords);
5476 // Null terminate the string.
5477 buffer.push_back(0);
5479 auto *Entry = CGObjC.CreateCStringLiteral(
5480 reinterpret_cast<char *>(buffer.data()), ObjCLabelType::LayoutBitMap);
5481 return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
5501CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
5502 CharUnits beginOffset, CharUnits endOffset,
5503 bool ForStrongLayout, bool HasMRCWeakIvars) {
5504 // If this is MRC, and we're either building a strong layout or there
5505 // are no weak ivars, bail out early.
5506 llvm::Type *PtrTy = CGM.Int8PtrTy;
5507 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
5508 !CGM.getLangOpts().ObjCAutoRefCount &&
5509 (ForStrongLayout || !HasMRCWeakIvars))
5510 return llvm::Constant::getNullValue(PtrTy);
5512 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
5513 SmallVector<const ObjCIvarDecl *, 32> ivars;
5515 // GC layout strings include the complete object layout, possibly
5516 // inaccurately in the non-fragile ABI; the runtime knows how to fix this
5519 // ARC layout strings only include the class's ivars. In non-fragile
5520 // runtimes, that means starting at InstanceStart, rounded up to word
5521 // alignment. In fragile runtimes, there's no InstanceStart, so it means
5522 // starting at the offset of the first ivar, rounded up to word alignment.
5524 // MRC weak layout strings follow the ARC style.
5525 CharUnits baseOffset;
5526 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
5527 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin(); IVD;
5528 IVD = IVD->getNextIvar())
5529 ivars.push_back(IVD);
5531 if (isNonFragileABI()) {
5532 baseOffset = beginOffset; // InstanceStart
5533 } else if (!ivars.empty()) {
5535 CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
5537 baseOffset = CharUnits::Zero();
5540 baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
5542 CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
5544 baseOffset = CharUnits::Zero();
5548 return llvm::Constant::getNullValue(PtrTy);
5550 IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
5552 builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
5553 [&](const ObjCIvarDecl *ivar) -> CharUnits {
5554 return CharUnits::fromQuantity(
5555 ComputeIvarBaseOffset(CGM, OMD, ivar));
5558 if (!builder.hasBitmapData())
5559 return llvm::Constant::getNullValue(PtrTy);
5561 llvm::SmallVector<unsigned char, 4> buffer;
5562 llvm::Constant *C = builder.buildBitmap(*this, buffer);
5564 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
5565 printf("\n%
s ivar layout
for class '%s':
",
5566 ForStrongLayout ? "strong
" : "weak
",
5567 OMD->getClassInterface()->getName().str().c_str());
5568 builder.dump(buffer);
5573llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
5574 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
5575 // FIXME: Avoid std::string in "Sel.
getAsString()
"
5578 CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
5579 return getConstantGEP(VMContext, Entry, 0, 0);
5582// FIXME: Merge into a single cstring creation function.
5583llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
5584 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
5587llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
5588 std::string TypeStr;
5589 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
5591 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
5593 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
5594 return getConstantGEP(VMContext, Entry, 0, 0);
5597llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
5599 std::string TypeStr =
5600 CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
5602 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
5604 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
5605 return getConstantGEP(VMContext, Entry, 0, 0);
5608// FIXME: Merge into a single cstring creation function.
5609llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
5610 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
5612 Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
5613 return getConstantGEP(VMContext, Entry, 0, 0);
5616// FIXME: Merge into a single cstring creation function.
5617// FIXME: This Decl should be more precise.
5619CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
5620 const Decl *Container) {
5621 std::string TypeStr =
5622 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
5623 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
5626void CGObjCMac::FinishModule() {
5629 // Emit the dummy bodies for any protocols which were referenced but
5631 for (auto &entry : Protocols) {
5632 llvm::GlobalVariable *global = entry.second;
5633 if (global->hasInitializer())
5636 ConstantInitBuilder builder(CGM);
5637 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
5638 values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
5639 values.add(GetClassName(entry.first->getName()));
5640 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
5641 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5642 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5643 values.finishAndSetAsInitializer(global);
5644 CGM.addCompilerUsedGlobal(global);
5647 // Add assembler directives to add lazy undefined symbol references
5648 // for classes which are referenced but not defined. This is
5649 // important for correct linker interaction.
5651 // FIXME: It would be nice if we had an LLVM construct for this.
5652 if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
5653 CGM.getTriple().isOSBinFormatMachO()) {
5654 SmallString<256> Asm;
5655 Asm += CGM.getModule().getModuleInlineAsm();
5656 if (!Asm.empty() && Asm.back() != '\n')
5659 llvm::raw_svector_ostream OS(Asm);
5660 for (const auto *Sym : DefinedSymbols)
5661 OS << "\t.objc_class_name_
" << Sym->getName() << "=0\n
"
5662 << "\t.globl .objc_class_name_
" << Sym->getName() << "\n
";
5663 for (const auto *Sym : LazySymbols)
5664 OS << "\t.lazy_reference .objc_class_name_
" << Sym->getName() << "\n
";
5665 for (const auto &Category : DefinedCategoryNames)
5666 OS << "\t.objc_category_name_
" << Category << "=0\n
"
5667 << "\t.globl .objc_category_name_
" << Category << "\n
";
5669 CGM.getModule().setModuleInlineAsm(OS.str());
5673CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
5674 : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
5675 ObjCEmptyVtableVar(nullptr) {
5681ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
5682 : VMContext(cgm.getLLVMContext()), CGM(cgm) {
5683 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5684 ASTContext &Ctx = CGM.getContext();
5685 unsigned ProgramAS = CGM.getDataLayout().getProgramAddressSpace();
5687 ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
5689 LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
5690 Int8PtrTy = CGM.Int8PtrTy;
5691 Int8PtrProgramASTy = llvm::PointerType::get(CGM.getLLVMContext(), ProgramAS);
5692 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
5694 // arm64 targets use "int" ivar offset variables. All others,
5695 // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
5696 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
5697 IvarOffsetVarTy = IntTy;
5699 IvarOffsetVarTy = LongTy;
5701 ObjectPtrTy = cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
5702 PtrObjectPtrTy = llvm::PointerType::getUnqual(VMContext);
5704 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
5706 // I'm not sure I like this. The implicit coordination is a bit
5707 // gross. We should solve this in a reasonable fashion because this
5708 // is a pretty common task (match some runtime data structure with
5709 // an LLVM data structure).
5711 // FIXME: This is leaked.
5712 // FIXME: Merge with rewriter code?
5714 // struct _objc_super {
5718 RecordDecl *RD = RecordDecl::Create(
5719 Ctx, TagTypeKind::Struct, Ctx.getTranslationUnitDecl(), SourceLocation(),
5720 SourceLocation(), &Ctx.Idents.get("_objc_super
"));
5721 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5722 nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
5723 false, ICIS_NoInit));
5724 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5725 nullptr, Ctx.getObjCClassType(), nullptr,
5726 nullptr, false, ICIS_NoInit));
5727 RD->completeDefinition();
5729 SuperCTy = Ctx.getCanonicalTagType(RD);
5730 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
5732 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
5733 SuperPtrTy = llvm::PointerType::getUnqual(VMContext);
5737 // char *attributes;
5739 PropertyTy = llvm::StructType::create("struct._prop_t
", Int8PtrTy, Int8PtrTy);
5741 // struct _prop_list_t {
5742 // uint32_t entsize; // sizeof(struct _prop_t)
5743 // uint32_t count_of_properties;
5744 // struct _prop_t prop_list[count_of_properties];
5746 PropertyListTy = llvm::StructType::create(
5747 "struct._prop_list_t
", IntTy, IntTy, llvm::ArrayType::get(PropertyTy, 0));
5748 // struct _prop_list_t *
5749 PropertyListPtrTy = llvm::PointerType::getUnqual(VMContext);
5751 // struct _objc_method {
5753 // char *method_type;
5756 MethodTy = llvm::StructType::create("struct._objc_method
", SelectorPtrTy,
5757 Int8PtrTy, Int8PtrProgramASTy);
5759 // struct _objc_cache *
5760 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache
");
5761 CachePtrTy = llvm::PointerType::getUnqual(VMContext);
5764ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
5765 : ObjCCommonTypesHelper(cgm) {
5766 // struct _objc_method_description {
5770 MethodDescriptionTy = llvm::StructType::create(
5771 "struct._objc_method_description
", SelectorPtrTy, Int8PtrTy);
5773 // struct _objc_method_description_list {
5775 // struct _objc_method_description[1];
5777 MethodDescriptionListTy =
5778 llvm::StructType::create("struct._objc_method_description_list
", IntTy,
5779 llvm::ArrayType::get(MethodDescriptionTy, 0));
5781 // struct _objc_method_description_list *
5782 MethodDescriptionListPtrTy = llvm::PointerType::getUnqual(VMContext);
5784 // Protocol description structures
5786 // struct _objc_protocol_extension {
5787 // uint32_t size; // sizeof(struct _objc_protocol_extension)
5788 // struct _objc_method_description_list *optional_instance_methods;
5789 // struct _objc_method_description_list *optional_class_methods;
5790 // struct _objc_property_list *instance_properties;
5791 // const char ** extendedMethodTypes;
5792 // struct _objc_property_list *class_properties;
5794 ProtocolExtensionTy = llvm::StructType::create(
5795 "struct._objc_protocol_extension
", IntTy, MethodDescriptionListPtrTy,
5796 MethodDescriptionListPtrTy, PropertyListPtrTy, Int8PtrPtrTy,
5799 // struct _objc_protocol_extension *
5800 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(VMContext);
5802 // Handle construction of Protocol and ProtocolList types
5804 // struct _objc_protocol {
5805 // struct _objc_protocol_extension *isa;
5806 // char *protocol_name;
5807 // struct _objc_protocol **_objc_protocol_list;
5808 // struct _objc_method_description_list *instance_methods;
5809 // struct _objc_method_description_list *class_methods;
5811 ProtocolTy = llvm::StructType::create(
5812 {ProtocolExtensionPtrTy, Int8PtrTy,
5813 llvm::PointerType::getUnqual(VMContext), MethodDescriptionListPtrTy,
5814 MethodDescriptionListPtrTy},
5815 "struct._objc_protocol
");
5818 llvm::StructType::create({llvm::PointerType::getUnqual(VMContext), LongTy,
5819 llvm::ArrayType::get(ProtocolTy, 0)},
5820 "struct._objc_protocol_list
");
5822 // struct _objc_protocol_list *
5823 ProtocolListPtrTy = llvm::PointerType::getUnqual(VMContext);
5825 ProtocolPtrTy = llvm::PointerType::getUnqual(VMContext);
5827 // Class description structures
5829 // struct _objc_ivar {
5834 IvarTy = llvm::StructType::create("struct._objc_ivar
", Int8PtrTy, Int8PtrTy,
5837 // struct _objc_ivar_list *
5838 IvarListTy = llvm::StructType::create(VMContext, "struct._objc_ivar_list
");
5839 IvarListPtrTy = llvm::PointerType::getUnqual(VMContext);
5841 // struct _objc_method_list *
5843 llvm::StructType::create(VMContext, "struct._objc_method_list
");
5844 MethodListPtrTy = llvm::PointerType::getUnqual(VMContext);
5846 // struct _objc_class_extension *
5847 ClassExtensionTy = llvm::StructType::create(
5848 "struct._objc_class_extension
", IntTy, Int8PtrTy, PropertyListPtrTy);
5849 ClassExtensionPtrTy = llvm::PointerType::getUnqual(VMContext);
5851 // struct _objc_class {
5853 // Class super_class;
5857 // long instance_size;
5858 // struct _objc_ivar_list *ivars;
5859 // struct _objc_method_list *methods;
5860 // struct _objc_cache *cache;
5861 // struct _objc_protocol_list *protocols;
5862 // char *ivar_layout;
5863 // struct _objc_class_ext *ext;
5865 ClassTy = llvm::StructType::create(
5866 {llvm::PointerType::getUnqual(VMContext),
5867 llvm::PointerType::getUnqual(VMContext), Int8PtrTy, LongTy, LongTy,
5868 LongTy, IvarListPtrTy, MethodListPtrTy, CachePtrTy, ProtocolListPtrTy,
5869 Int8PtrTy, ClassExtensionPtrTy},
5870 "struct._objc_class
");
5872 ClassPtrTy = llvm::PointerType::getUnqual(VMContext);
5874 // struct _objc_category {
5875 // char *category_name;
5876 // char *class_name;
5877 // struct _objc_method_list *instance_method;
5878 // struct _objc_method_list *class_method;
5879 // struct _objc_protocol_list *protocols;
5880 // uint32_t size; // sizeof(struct _objc_category)
5881 // struct _objc_property_list *instance_properties;// category's @property
5882 // struct _objc_property_list *class_properties;
5884 CategoryTy = llvm::StructType::create(
5885 "struct._objc_category
", Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5886 MethodListPtrTy, ProtocolListPtrTy, IntTy, PropertyListPtrTy,
5889 // Global metadata structures
5891 // struct _objc_symtab {
5892 // long sel_ref_cnt;
5894 // short cls_def_cnt;
5895 // short cat_def_cnt;
5896 // char *defs[cls_def_cnt + cat_def_cnt];
5898 SymtabTy = llvm::StructType::create("struct._objc_symtab
", LongTy,
5899 SelectorPtrTy, ShortTy, ShortTy,
5900 llvm::ArrayType::get(Int8PtrTy, 0));
5901 SymtabPtrTy = llvm::PointerType::getUnqual(VMContext);
5903 // struct _objc_module {
5905 // long size; // sizeof(struct _objc_module)
5907 // struct _objc_symtab* symtab;
5909 ModuleTy = llvm::StructType::create("struct._objc_module
", LongTy, LongTy,
5910 Int8PtrTy, SymtabPtrTy);
5912 // FIXME: This is the size of the setjmp buffer and should be target
5913 // specific. 18 is what's used on 32-bit X86.
5914 uint64_t SetJmpBufferSize = 18;
5917 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
5919 ExceptionDataTy = llvm::StructType::create(
5920 "struct._objc_exception_data
",
5921 llvm::ArrayType::get(CGM.Int32Ty, SetJmpBufferSize), StackPtrTy);
5924ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(
5925 CodeGen::CodeGenModule &cgm)
5926 : ObjCCommonTypesHelper(cgm) {
5927 // struct _method_list_t {
5928 // uint32_t entsize; // sizeof(struct _objc_method)
5929 // uint32_t method_count;
5930 // struct _objc_method method_list[method_count];
5933 llvm::StructType::create("struct.__method_list_t
", IntTy, IntTy,
5934 llvm::ArrayType::get(MethodTy, 0));
5935 // struct method_list_t *
5936 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);
5938 // struct _protocol_t {
5940 // const char * const protocol_name;
5941 // const struct _protocol_list_t * protocol_list; // super protocols
5942 // const struct method_list_t * const instance_methods;
5943 // const struct method_list_t * const class_methods;
5944 // const struct method_list_t *optionalInstanceMethods;
5945 // const struct method_list_t *optionalClassMethods;
5946 // const struct _prop_list_t * properties;
5947 // const uint32_t size; // sizeof(struct _protocol_t)
5948 // const uint32_t flags; // = 0
5949 // const char ** extendedMethodTypes;
5950 // const char *demangledName;
5951 // const struct _prop_list_t * class_properties;
5954 ProtocolnfABITy = llvm::StructType::create(
5955 "struct._protocol_t
", ObjectPtrTy, Int8PtrTy,
5956 llvm::PointerType::getUnqual(VMContext), MethodListnfABIPtrTy,
5957 MethodListnfABIPtrTy, MethodListnfABIPtrTy, MethodListnfABIPtrTy,
5958 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy, Int8PtrTy,
5961 // struct _protocol_t*
5962 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);
5964 // struct _protocol_list_t {
5965 // long protocol_count; // Note, this is 32/64 bit
5966 // struct _protocol_t *[protocol_count];
5968 ProtocolListnfABITy = llvm::StructType::create(
5969 {LongTy, llvm::ArrayType::get(ProtocolnfABIPtrTy, 0)},
5970 "struct._objc_protocol_list
");
5972 // struct _objc_protocol_list*
5973 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);
5976 // unsigned [long] int *offset; // pointer to ivar offset location
5979 // uint32_t alignment;
5982 IvarnfABITy = llvm::StructType::create(
5983 "struct._ivar_t
", llvm::PointerType::getUnqual(VMContext), Int8PtrTy,
5984 Int8PtrTy, IntTy, IntTy);
5986 // struct _ivar_list_t {
5987 // uint32 entsize; // sizeof(struct _ivar_t)
5989 // struct _iver_t list[count];
5992 llvm::StructType::create("struct._ivar_list_t
", IntTy, IntTy,
5993 llvm::ArrayType::get(IvarnfABITy, 0));
5995 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);
5997 // struct _class_ro_t {
5998 // uint32_t const flags;
5999 // uint32_t const instanceStart;
6000 // uint32_t const instanceSize;
6001 // uint32_t const reserved; // only when building for 64bit targets
6002 // const uint8_t * const ivarLayout;
6003 // const char *const name;
6004 // const struct _method_list_t * const baseMethods;
6005 // const struct _objc_protocol_list *const baseProtocols;
6006 // const struct _ivar_list_t *const ivars;
6007 // const uint8_t * const weakIvarLayout;
6008 // const struct _prop_list_t * const properties;
6011 // FIXME. Add 'reserved' field in 64bit abi mode!
6012 ClassRonfABITy = llvm::StructType::create(
6013 "struct._class_ro_t
", IntTy, IntTy, IntTy, Int8PtrTy, Int8PtrTy,
6014 MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, IvarListnfABIPtrTy,
6015 Int8PtrTy, PropertyListPtrTy);
6017 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
6018 ImpnfABITy = CGM.DefaultPtrTy;
6020 // struct _class_t {
6021 // struct _class_t *isa;
6022 // struct _class_t * const superclass;
6025 // struct class_ro_t *ro;
6028 ClassnfABITy = llvm::StructType::create(
6029 {llvm::PointerType::getUnqual(VMContext),
6030 llvm::PointerType::getUnqual(VMContext), CachePtrTy,
6031 llvm::PointerType::getUnqual(VMContext),
6032 llvm::PointerType::getUnqual(VMContext)},
6035 // LLVM for struct _class_t *
6036 ClassnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);
6038 // struct _category_t {
6039 // const char * const name;
6040 // struct _class_t *const cls;
6041 // const struct _method_list_t * const instance_methods;
6042 // const struct _method_list_t * const class_methods;
6043 // const struct _protocol_list_t * const protocols;
6044 // const struct _prop_list_t * const properties;
6045 // const struct _prop_list_t * const class_properties;
6046 // const uint32_t size;
6048 CategorynfABITy = llvm::StructType::create(
6049 "struct._category_t
", Int8PtrTy, ClassnfABIPtrTy, MethodListnfABIPtrTy,
6050 MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, PropertyListPtrTy,
6051 PropertyListPtrTy, IntTy);
6053 // New types for nonfragile abi messaging.
6054 CodeGen::CodeGenTypes &Types = CGM.getTypes();
6055 ASTContext &Ctx = CGM.getContext();
6057 // MessageRefTy - LLVM for:
6058 // struct _message_ref_t {
6063 // First the clang type for struct _message_ref_t
6064 RecordDecl *RD = RecordDecl::Create(
6065 Ctx, TagTypeKind::Struct, Ctx.getTranslationUnitDecl(), SourceLocation(),
6066 SourceLocation(), &Ctx.Idents.get("_message_ref_t
"));
6067 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6068 nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false,
6070 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6071 nullptr, Ctx.getObjCSelType(), nullptr, nullptr,
6072 false, ICIS_NoInit));
6073 RD->completeDefinition();
6075 MessageRefCTy = Ctx.getCanonicalTagType(RD);
6076 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
6077 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
6079 // MessageRefPtrTy - LLVM for struct _message_ref_t*
6080 MessageRefPtrTy = llvm::PointerType::getUnqual(VMContext);
6082 // SuperMessageRefTy - LLVM for:
6083 // struct _super_message_ref_t {
6084 // SUPER_IMP messenger;
6087 SuperMessageRefTy = llvm::StructType::create("struct._super_message_ref_t
",
6088 ImpnfABITy, SelectorPtrTy);
6090 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
6091 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(VMContext);
6093 // struct objc_typeinfo {
6094 // const void** vtable; // objc_ehtype_vtable + 2
6095 // const char* name; // c++ typeinfo string
6098 EHTypeTy = llvm::StructType::create("struct._objc_typeinfo
",
6099 llvm::PointerType::getUnqual(VMContext),
6100 Int8PtrTy, ClassnfABIPtrTy);
6101 EHTypePtrTy = llvm::PointerType::getUnqual(VMContext);
6104llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
6105 FinishNonFragileABIModule();
6110void CGObjCNonFragileABIMac::AddModuleClassList(
6111 ArrayRef<llvm::GlobalValue *> Container, StringRef SymbolName,
6112 StringRef SectionName) {
6113 unsigned NumClasses = Container.size();
6118 SmallVector<llvm::Constant *, 8> Symbols(NumClasses);
6119 for (unsigned i = 0; i < NumClasses; i++)
6120 Symbols[i] = Container[i];
6122 llvm::Constant *Init = llvm::ConstantArray::get(
6123 llvm::ArrayType::get(ObjCTypes.Int8PtrTy, Symbols.size()), Symbols);
6125 // Section name is obtained by calling GetSectionName, which returns
6126 // sections in the __DATA segment on MachO.
6127 assert((!CGM.getTriple().isOSBinFormatMachO() ||
6128 SectionName.starts_with("__DATA
")) &&
6129 "SectionName expected to start with __DATA on
MachO");
6130 llvm::GlobalVariable *GV = new llvm::GlobalVariable(
6131 CGM.getModule(), Init->getType(), false,
6132 llvm::GlobalValue::PrivateLinkage, Init, SymbolName);
6133 GV->setAlignment(CGM.getDataLayout().getABITypeAlign(Init->getType()));
6134 GV->setSection(SectionName);
6135 CGM.addCompilerUsedGlobal(GV);
6138void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
6139 // nonfragile abi has no module definition.
6141 // Build list of all implemented class addresses in array
6142 // L_OBJC_LABEL_CLASS_$.
6144 for (unsigned i = 0, NumClasses = ImplementedClasses.size(); i < NumClasses;
6146 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
6148 if (ObjCImplementationDecl *IMP = ID->getImplementation())
6149 // We are implementing a weak imported interface. Give it external linkage
6150 if (ID->isWeakImported() && !IMP->isWeakImported()) {
6151 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
6152 DefinedMetaClasses[i]->setLinkage(
6153 llvm::GlobalVariable::ExternalLinkage);
6158 DefinedClasses, "OBJC_LABEL_CLASS_$
",
6159 GetSectionName("__objc_classlist
", "regular,no_dead_strip
"));
6162 DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$
",
6163 GetSectionName("__objc_nlclslist
", "regular,no_dead_strip
"));
6165 // Build list of all implemented category addresses in array
6166 // L_OBJC_LABEL_CATEGORY_$.
6167 AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$
",
6168 GetSectionName("__objc_catlist
", "regular,no_dead_strip
"));
6170 DefinedStubCategories, "OBJC_LABEL_STUB_CATEGORY_$
",
6171 GetSectionName("__objc_catlist2
", "regular,no_dead_strip
"));
6173 DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$
",
6174 GetSectionName("__objc_nlcatlist
", "regular,no_dead_strip
"));
6183bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
6184 // At various points we've experimented with using vtable-based
6185 // dispatch for all methods.
6186 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
6187 case CodeGenOptions::Legacy:
6189 case CodeGenOptions::NonLegacy:
6191 case CodeGenOptions::Mixed:
6195 // If so, see whether this selector is in the white-list of things which must
6196 // use the new dispatch convention. We lazily build a dense set for this.
6197 if (VTableDispatchMethods.empty()) {
6198 VTableDispatchMethods.insert(GetNullarySelector("alloc
"));
6199 VTableDispatchMethods.insert(GetNullarySelector("class"));
6200 VTableDispatchMethods.insert(GetNullarySelector("self
"));
6201 VTableDispatchMethods.insert(GetNullarySelector("isFlipped
"));
6202 VTableDispatchMethods.insert(GetNullarySelector("length"));
6203 VTableDispatchMethods.insert(GetNullarySelector("count
"));
6205 // These are vtable-based if GC is disabled.
6206 // Optimistically use vtable dispatch for hybrid compiles.
6207 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
6208 VTableDispatchMethods.insert(GetNullarySelector("retain
"));
6209 VTableDispatchMethods.insert(GetNullarySelector("release
"));
6210 VTableDispatchMethods.insert(GetNullarySelector("autorelease
"));
6213 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone
"));
6214 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass
"));
6215 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector
"));
6216 VTableDispatchMethods.insert(GetUnarySelector("objectForKey
"));
6217 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex
"));
6218 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString
"));
6219 VTableDispatchMethods.insert(GetUnarySelector("isEqual
"));
6221 // These are vtable-based if GC is enabled.
6222 // Optimistically use vtable dispatch for hybrid compiles.
6223 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
6224 VTableDispatchMethods.insert(GetNullarySelector("hash
"));
6225 VTableDispatchMethods.insert(GetUnarySelector("addObject
"));
6227 // "countByEnumeratingWithState:objects:count
"
6228 const IdentifierInfo *KeyIdents[] = {
6229 &CGM.getContext().Idents.get("countByEnumeratingWithState
"),
6230 &CGM.getContext().Idents.get("objects
"),
6231 &CGM.getContext().Idents.get("count
")};
6232 VTableDispatchMethods.insert(
6233 CGM.getContext().Selectors.getSelector(3, KeyIdents));
6237 return VTableDispatchMethods.count(Sel);
6255llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassRoTInitializer(
6256 unsigned flags, unsigned InstanceStart, unsigned InstanceSize,
6257 const ObjCImplementationDecl *ID) {
6258 std::string ClassName = std::string(ID->getObjCRuntimeNameAsString());
6260 CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
6261 CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
6263 bool hasMRCWeak = false;
6264 if (CGM.getLangOpts().ObjCAutoRefCount)
6265 flags |= NonFragileABI_Class_CompiledByARC;
6266 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
6267 flags |= NonFragileABI_Class_HasMRCWeakIvars;
6269 ConstantInitBuilder builder(CGM);
6270 auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy);
6272 values.addInt(ObjCTypes.IntTy, flags);
6273 values.addInt(ObjCTypes.IntTy, InstanceStart);
6274 values.addInt(ObjCTypes.IntTy, InstanceSize);
6275 values.add((flags & NonFragileABI_Class_Meta)
6276 ? GetIvarLayoutName(nullptr, ObjCTypes)
6277 : BuildStrongIvarLayout(ID, beginInstance, endInstance));
6278 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
6280 // const struct _method_list_t * const baseMethods;
6281 SmallVector<const ObjCMethodDecl *, 16> methods;
6282 if (flags & NonFragileABI_Class_Meta) {
6283 for (const auto *MD : ID->class_methods())
6284 if (!MD->isDirectMethod())
6285 methods.push_back(MD);
6287 for (const auto *MD : ID->instance_methods())
6288 if (!MD->isDirectMethod())
6289 methods.push_back(MD);
6292 llvm::Constant *MethListPtr = emitMethodList(
6293 ID->getObjCRuntimeNameAsString(),
6294 (flags & NonFragileABI_Class_Meta) ? MethodListType::ClassMethods
6295 : MethodListType::InstanceMethods,
6298 const PointerAuthSchema &MethListSchema =
6299 CGM.getCodeGenOpts().PointerAuth.ObjCMethodListPointer;
6300 if (!MethListPtr->isNullValue())
6301 values.addSignedPointer(MethListPtr, MethListSchema, GlobalDecl(),
6304 values.add(MethListPtr);
6306 const ObjCInterfaceDecl *OID = ID->getClassInterface();
6307 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer
");
6308 values.add(EmitProtocolList("_OBJC_CLASS_PROTOCOLS_$_
" +
6309 OID->getObjCRuntimeNameAsString(),
6310 OID->all_referenced_protocol_begin(),
6311 OID->all_referenced_protocol_end()));
6313 if (flags & NonFragileABI_Class_Meta) {
6314 values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy);
6315 values.add(GetIvarLayoutName(nullptr, ObjCTypes));
6316 values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_
" +
6317 ID->getObjCRuntimeNameAsString(),
6318 ID, ID->getClassInterface(), ObjCTypes, true));
6320 values.add(EmitIvarList(ID));
6321 values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak));
6322 values.add(EmitPropertyList("_OBJC_$_PROP_LIST_
" +
6323 ID->getObjCRuntimeNameAsString(),
6324 ID, ID->getClassInterface(), ObjCTypes, false));
6327 llvm::SmallString<64> roLabel;
6328 llvm::raw_svector_ostream(roLabel)
6329 << ((flags & NonFragileABI_Class_Meta) ? "_OBJC_METACLASS_RO_$_
"
6330 : "_OBJC_CLASS_RO_$_
")
6333 return finishAndCreateGlobal(values, roLabel, CGM);
6346llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassObject(
6347 const ObjCInterfaceDecl *CI, bool isMetaclass, llvm::Constant *IsAGV,
6348 llvm::Constant *SuperClassGV, llvm::Constant *ClassRoGV,
6349 bool HiddenVisibility) {
6350 ConstantInitBuilder builder(CGM);
6351 auto values = builder.beginStruct(ObjCTypes.ClassnfABITy);
6352 const PointerAuthOptions &PointerAuthOpts = CGM.getCodeGenOpts().PointerAuth;
6353 values.addSignedPointer(IsAGV, PointerAuthOpts.ObjCIsaPointers, GlobalDecl(),
6356 values.addSignedPointer(SuperClassGV, PointerAuthOpts.ObjCSuperPointers,
6357 GlobalDecl(), QualType());
6359 values.addNullPointer(ObjCTypes.ClassnfABIPtrTy);
6361 values.add(ObjCEmptyCacheVar);
6362 values.add(ObjCEmptyVtableVar);
6364 values.addSignedPointer(ClassRoGV, PointerAuthOpts.ObjCClassROPointers,
6365 GlobalDecl(), QualType());
6367 llvm::GlobalVariable *GV = cast<llvm::GlobalVariable>(
6368 GetClassGlobal(CI, isMetaclass, ForDefinition));
6369 values.finishAndSetAsInitializer(GV);
6371 if (CGM.getTriple().isOSBinFormatMachO())
6372 GV->setSection("__DATA, __objc_data
");
6373 GV->setAlignment(CGM.getDataLayout().getABITypeAlign(ObjCTypes.ClassnfABITy));
6374 if (!CGM.getTriple().isOSBinFormatCOFF())
6375 if (HiddenVisibility)
6376 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6380bool CGObjCNonFragileABIMac::ImplementationIsNonLazy(
6381 const ObjCImplDecl *OD) const {
6382 return OD->getClassMethod(GetNullarySelector("load
")) != nullptr ||
6383 OD->getClassInterface()->hasAttr<ObjCNonLazyClassAttr>() ||
6384 OD->hasAttr<ObjCNonLazyClassAttr>();
6387void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
6388 uint32_t &InstanceStart,
6389 uint32_t &InstanceSize) {
6390 const ASTRecordLayout &RL =
6391 CGM.getContext().getASTObjCInterfaceLayout(OID->getClassInterface());
6393 // InstanceSize is really instance end.
6394 InstanceSize = RL.getDataSize().getQuantity();
6396 // If there are no fields, the start is the same as the end.
6397 if (!RL.getFieldCount())
6398 InstanceStart = InstanceSize;
6400 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
6403static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM,
6405 IdentifierInfo &II = CGM.getContext().Idents.get(Name);
6406 TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
6407 DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
6409 const VarDecl *VD = nullptr;
6410 for (const auto *Result : DC->lookup(&II))
6411 if ((VD = dyn_cast<VarDecl>(Result)))
6415 return llvm::GlobalValue::DLLImportStorageClass;
6416 if (VD->hasAttr<DLLExportAttr>())
6417 return llvm::GlobalValue::DLLExportStorageClass;
6418 if (VD->hasAttr<DLLImportAttr>())
6419 return llvm::GlobalValue::DLLImportStorageClass;
6420 return llvm::GlobalValue::DefaultStorageClass;
6423void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
6424 if (!ObjCEmptyCacheVar) {
6425 ObjCEmptyCacheVar = new llvm::GlobalVariable(
6426 CGM.getModule(), ObjCTypes.CacheTy, false,
6427 llvm::GlobalValue::ExternalLinkage, nullptr, "_objc_empty_cache
");
6428 if (CGM.getTriple().isOSBinFormatCOFF())
6429 ObjCEmptyCacheVar->setDLLStorageClass(
6430 getStorage(CGM, "_objc_empty_cache
"));
6432 // Only OS X with deployment version <10.9 use the empty vtable symbol
6433 const llvm::Triple &Triple = CGM.getTarget().getTriple();
6434 if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9))
6435 ObjCEmptyVtableVar = new llvm::GlobalVariable(
6436 CGM.getModule(), ObjCTypes.ImpnfABITy, false,
6437 llvm::GlobalValue::ExternalLinkage, nullptr, "_objc_empty_vtable
");
6439 ObjCEmptyVtableVar = llvm::ConstantPointerNull::get(CGM.DefaultPtrTy);
6442 // FIXME: Is this correct (that meta class size is never computed)?
6443 uint32_t InstanceStart =
6444 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
6445 uint32_t InstanceSize = InstanceStart;
6446 uint32_t flags = NonFragileABI_Class_Meta;
6448 llvm::Constant *SuperClassGV, *IsAGV;
6450 const auto *CI = ID->getClassInterface();
6451 assert(CI && "CGObjCNonFragileABIMac::GenerateClass -
class is 0
");
6453 // Build the flags for the metaclass.
6454 bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF())
6455 ? !CI->hasAttr<DLLExportAttr>()
6456 : CI->getVisibility() == HiddenVisibility;
6458 flags |= NonFragileABI_Class_Hidden;
6460 // FIXME: why is this flag set on the metaclass?
6461 // ObjC metaclasses have no fields and don't really get constructed.
6462 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
6463 flags |= NonFragileABI_Class_HasCXXStructors;
6464 if (!ID->hasNonZeroConstructors())
6465 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
6468 if (!CI->getSuperClass()) {
6470 flags |= NonFragileABI_Class_Root;
6472 SuperClassGV = GetClassGlobal(CI, /*metaclass*/ false, NotForDefinition);
6473 IsAGV = GetClassGlobal(CI, /*metaclass*/ true, NotForDefinition);
6475 // Has a root. Current class is not a root.
6476 const ObjCInterfaceDecl *Root = ID->getClassInterface();
6477 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
6480 const auto *Super = CI->getSuperClass();
6481 IsAGV = GetClassGlobal(Root, /*metaclass*/ true, NotForDefinition);
6482 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ true, NotForDefinition);
6485 llvm::GlobalVariable *CLASS_RO_GV =
6486 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
6488 llvm::GlobalVariable *MetaTClass = BuildClassObject(
6489 CI, /*metaclass*/ true, IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden);
6490 CGM.setGVProperties(MetaTClass, CI);
6491 DefinedMetaClasses.push_back(MetaTClass);
6493 // Metadata for the class
6496 flags |= NonFragileABI_Class_Hidden;
6498 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
6499 flags |= NonFragileABI_Class_HasCXXStructors;
6501 // Set a flag to enable a runtime optimization when a class has
6502 // fields that require destruction but which don't require
6503 // anything except zero-initialization during construction. This
6504 // is most notably true of __strong and __weak types, but you can
6505 // also imagine there being C++ types with non-trivial default
6506 // constructors that merely set all fields to null.
6507 if (!ID->hasNonZeroConstructors())
6508 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
6511 if (hasObjCExceptionAttribute(CGM.getContext(), CI))
6512 flags |= NonFragileABI_Class_Exception;
6514 if (!CI->getSuperClass()) {
6515 flags |= NonFragileABI_Class_Root;
6516 SuperClassGV = nullptr;
6518 // Has a root. Current class is not a root.
6519 const auto *Super = CI->getSuperClass();
6520 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ false, NotForDefinition);
6523 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
6525 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
6527 llvm::GlobalVariable *ClassMD =
6528 BuildClassObject(CI, /*metaclass*/ false, MetaTClass, SuperClassGV,
6529 CLASS_RO_GV, classIsHidden);
6530 CGM.setGVProperties(ClassMD, CI);
6531 DefinedClasses.push_back(ClassMD);
6532 ImplementedClasses.push_back(CI);
6534 // Determine if this class is also "non-lazy
".
6535 if (ImplementationIsNonLazy(ID))
6536 DefinedNonLazyClasses.push_back(ClassMD);
6538 // Force the definition of the EHType if necessary.
6539 if (flags & NonFragileABI_Class_Exception)
6540 (void)GetInterfaceEHType(CI, ForDefinition);
6541 // Make sure method definition entries are all clear for next implementation.
6542 MethodDefinitions.clear();
6554CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
6555 const ObjCProtocolDecl *PD) {
6557 // This routine is called for @protocol only. So, we must build definition
6558 // of protocol's meta-data (not a reference to it!)
6559 assert(!PD->isNonRuntimeProtocol() &&
6560 "attempting to get a protocol ref to a
static protocol.
");
6561 llvm::Constant *Init = GetOrEmitProtocol(PD);
6563 std::string ProtocolName("_OBJC_PROTOCOL_REFERENCE_$_
");
6564 ProtocolName += PD->getObjCRuntimeNameAsString();
6566 CharUnits Align = CGF.getPointerAlign();
6568 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
6570 return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
6571 PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
6572 llvm::GlobalValue::WeakAnyLinkage, Init,
6575 GetSectionName("__objc_protorefs
", "coalesced,no_dead_strip
"));
6576 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6577 PTGV->setAlignment(Align.getAsAlign());
6578 if (!CGM.getTriple().isOSBinFormatMachO())
6579 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName));
6580 CGM.addUsedGlobal(PTGV);
6581 return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
6596void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
6597 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
6598 const char *Prefix = "_OBJC_$_CATEGORY_
";
6600 llvm::SmallString<64> ExtCatName(Prefix);
6601 ExtCatName += Interface->getObjCRuntimeNameAsString();
6602 ExtCatName += "_$_
";
6603 ExtCatName += OCD->getNameAsString();
6605 ConstantInitBuilder builder(CGM);
6606 auto values = builder.beginStruct(ObjCTypes.CategorynfABITy);
6607 values.add(GetClassName(OCD->getIdentifier()->getName()));
6608 // meta-class entry symbol
6609 values.add(GetClassGlobal(Interface, /*metaclass*/ false, NotForDefinition));
6610 std::string listName =
6611 (Interface->getObjCRuntimeNameAsString() + "_$_
" + OCD->getName()).str();
6613 SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
6614 SmallVector<const ObjCMethodDecl *, 8> classMethods;
6615 for (const auto *MD : OCD->methods()) {
6616 if (MD->isDirectMethod())
6618 if (MD->isInstanceMethod()) {
6619 instanceMethods.push_back(MD);
6621 classMethods.push_back(MD);
6625 llvm::Constant *InstanceMethodList = emitMethodList(
6626 listName, MethodListType::CategoryInstanceMethods, instanceMethods);
6627 const PointerAuthSchema &MethListSchema =
6628 CGM.getCodeGenOpts().PointerAuth.ObjCMethodListPointer;
6629 if (!InstanceMethodList->isNullValue())
6630 values.addSignedPointer(InstanceMethodList, MethListSchema, GlobalDecl(),
6633 values.add(InstanceMethodList);
6635 llvm::Constant *ClassMethodList = emitMethodList(
6636 listName, MethodListType::CategoryClassMethods, classMethods);
6637 if (!ClassMethodList->isNullValue())
6638 values.addSignedPointer(ClassMethodList, MethListSchema, GlobalDecl(),
6641 values.add(ClassMethodList);
6643 // Keep track of whether we have actual metadata to emit.
6644 bool isEmptyCategory =
6645 InstanceMethodList->isNullValue() && ClassMethodList->isNullValue();
6647 const ObjCCategoryDecl *Category =
6648 Interface->FindCategoryDeclaration(OCD->getIdentifier());
6650 SmallString<256> ExtName;
6651 llvm::raw_svector_ostream(ExtName)
6652 << Interface->getObjCRuntimeNameAsString() << "_$_
" << OCD->getName();
6654 EmitProtocolList("_OBJC_CATEGORY_PROTOCOLS_$_
" +
6655 Interface->getObjCRuntimeNameAsString() + "_$_
" +
6656 Category->getName(),
6657 Category->protocol_begin(), Category->protocol_end());
6658 auto propertyList = EmitPropertyList("_OBJC_$_PROP_LIST_
" + ExtName.str(),
6659 OCD, Category, ObjCTypes, false);
6660 auto classPropertyList =
6661 EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_
" + ExtName.str(), OCD,
6662 Category, ObjCTypes, true);
6663 values.add(protocolList);
6664 values.add(propertyList);
6665 values.add(classPropertyList);
6666 isEmptyCategory &= protocolList->isNullValue() &&
6667 propertyList->isNullValue() &&
6668 classPropertyList->isNullValue();
6670 values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy);
6671 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
6672 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
6675 if (isEmptyCategory) {
6676 // Empty category, don't emit any metadata.
6678 MethodDefinitions.clear();
6683 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
6684 values.addInt(ObjCTypes.IntTy, Size);
6686 llvm::GlobalVariable *GCATV =
6687 finishAndCreateGlobal(values, ExtCatName.str(), CGM);
6688 CGM.addCompilerUsedGlobal(GCATV);
6689 if (Interface->hasAttr<ObjCClassStubAttr>())
6690 DefinedStubCategories.push_back(GCATV);
6692 DefinedCategories.push_back(GCATV);
6694 // Determine if this category is also "non-lazy
".
6695 if (ImplementationIsNonLazy(OCD))
6696 DefinedNonLazyCategories.push_back(GCATV);
6697 // method definition entries must be clear for next implementation.
6698 MethodDefinitions.clear();
6710void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
6711 const ObjCMethodDecl *MD,
6713 auto method = builder.beginStruct(ObjCTypes.MethodTy);
6714 method.add(GetMethodVarName(MD->getSelector()));
6715 method.add(GetMethodVarType(MD));
6718 // Protocol methods have no implementation. So, this entry is always NULL.
6719 method.addNullPointer(ObjCTypes.Int8PtrProgramASTy);
6721 llvm::Function *fn = GetMethodDefinition(MD);
6722 assert(fn && "no definition
for method?
");
6723 if (const PointerAuthSchema &Schema =
6724 CGM.getCodeGenOpts().PointerAuth.ObjCMethodListFunctionPointers) {
6725 llvm::Constant *Bitcast =
6726 llvm::ConstantExpr::getBitCast(fn, ObjCTypes.Int8PtrProgramASTy);
6727 method.addSignedPointer(Bitcast, Schema, GlobalDecl(), QualType());
6732 method.finishAndAddTo(builder);
6743llvm::Constant *CGObjCNonFragileABIMac::emitMethodList(
6744 Twine name, MethodListType kind, ArrayRef<const ObjCMethodDecl *> methods) {
6745 // Return null for empty list.
6746 if (methods.empty())
6747 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
6752 case MethodListType::CategoryInstanceMethods:
6753 prefix = "_OBJC_$_CATEGORY_INSTANCE_METHODS_
";
6754 forProtocol = false;
6756 case MethodListType::CategoryClassMethods:
6757 prefix = "_OBJC_$_CATEGORY_CLASS_METHODS_
";
6758 forProtocol = false;
6760 case MethodListType::InstanceMethods:
6761 prefix = "_OBJC_$_INSTANCE_METHODS_
";
6762 forProtocol = false;
6764 case MethodListType::ClassMethods:
6765 prefix = "_OBJC_$_CLASS_METHODS_
";
6766 forProtocol = false;
6769 case MethodListType::ProtocolInstanceMethods:
6770 prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_
";
6773 case MethodListType::ProtocolClassMethods:
6774 prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_
";
6777 case MethodListType::OptionalProtocolInstanceMethods:
6778 prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_
";
6781 case MethodListType::OptionalProtocolClassMethods:
6782 prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_
";
6787 ConstantInitBuilder builder(CGM);
6788 auto values = builder.beginStruct();
6790 // sizeof(struct _objc_method)
6791 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
6792 values.addInt(ObjCTypes.IntTy, Size);
6794 values.addInt(ObjCTypes.IntTy, methods.size());
6795 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
6796 for (auto MD : methods)
6797 emitMethodConstant(methodArray, MD, forProtocol);
6798 methodArray.finishAndAddTo(values);
6800 llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM);
6801 CGM.addCompilerUsedGlobal(GV);
6807llvm::GlobalVariable *
6808CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6809 const ObjCIvarDecl *Ivar) {
6810 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
6811 llvm::SmallString<64> Name("OBJC_IVAR_$_
");
6812 Name += Container->getObjCRuntimeNameAsString();
6814 Name += Ivar->getName();
6815 llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name);
6816 if (!IvarOffsetGV) {
6817 IvarOffsetGV = new llvm::GlobalVariable(
6818 CGM.getModule(), ObjCTypes.IvarOffsetVarTy, false,
6819 llvm::GlobalValue::ExternalLinkage, nullptr, Name.str());
6820 if (CGM.getTriple().isOSBinFormatCOFF()) {
6821 bool IsPrivateOrPackage =
6822 Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6823 Ivar->getAccessControl() == ObjCIvarDecl::Package;
6825 const ObjCInterfaceDecl *ContainingID = Ivar->getContainingInterface();
6827 if (ContainingID->hasAttr<DLLImportAttr>())
6828 IvarOffsetGV->setDLLStorageClass(
6829 llvm::GlobalValue::DLLImportStorageClass);
6830 else if (ContainingID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage)
6831 IvarOffsetGV->setDLLStorageClass(
6832 llvm::GlobalValue::DLLExportStorageClass);
6835 return IvarOffsetGV;
6839CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6840 const ObjCIvarDecl *Ivar,
6841 unsigned long int Offset) {
6842 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
6843 IvarOffsetGV->setInitializer(
6844 llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset));
6845 IvarOffsetGV->setAlignment(
6846 CGM.getDataLayout().getABITypeAlign(ObjCTypes.IvarOffsetVarTy));
6848 if (!CGM.getTriple().isOSBinFormatCOFF()) {
6849 // FIXME: This matches gcc, but shouldn't the visibility be set on the use
6850 // as well (i.e., in ObjCIvarOffsetVariable).
6851 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6852 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
6853 ID->getVisibility() == HiddenVisibility)
6854 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6856 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
6859 // If ID's layout is known, then make the global constant. This serves as a
6860 // useful assertion: we'll never use this variable to calculate ivar offsets,
6861 // so if the runtime tries to patch it then we should crash.
6862 if (isClassLayoutKnownStatically(ID))
6863 IvarOffsetGV->setConstant(true);
6865 if (CGM.getTriple().isOSBinFormatMachO())
6866 IvarOffsetGV->setSection("__DATA, __objc_ivar
");
6867 return IvarOffsetGV;
6888CGObjCNonFragileABIMac::EmitIvarList(const ObjCImplementationDecl *ID) {
6890 ConstantInitBuilder builder(CGM);
6891 auto ivarList = builder.beginStruct();
6892 ivarList.addInt(ObjCTypes.IntTy,
6893 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy));
6894 auto ivarCountSlot = ivarList.addPlaceholder();
6895 auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy);
6897 const ObjCInterfaceDecl *OID = ID->getClassInterface();
6898 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface
");
6900 // FIXME. Consolidate this with similar code in GenerateClass.
6902 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin(); IVD;
6903 IVD = IVD->getNextIvar()) {
6904 // Ignore unnamed bit-fields.
6905 if (!IVD->getDeclName())
6908 auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy);
6909 ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD,
6910 ComputeIvarBaseOffset(CGM, ID, IVD)));
6911 ivar.add(GetMethodVarName(IVD->getIdentifier()));
6912 ivar.add(GetMethodVarType(IVD));
6913 llvm::Type *FieldTy = CGM.getTypes().ConvertTypeForMem(IVD->getType());
6914 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
6916 CGM.getContext().getPreferredTypeAlign(IVD->getType().getTypePtr()) >>
6918 Align = llvm::Log2_32(Align);
6919 ivar.addInt(ObjCTypes.IntTy, Align);
6920 // NOTE. Size of a bitfield does not match gcc's, because of the
6921 // way bitfields are treated special in each. But I am told that
6922 // 'size' for bitfield ivars is ignored by the runtime so it does
6923 // not matter. If it matters, there is enough info to get the
6925 ivar.addInt(ObjCTypes.IntTy, Size);
6926 ivar.finishAndAddTo(ivars);
6928 // Return null for empty list.
6929 if (ivars.empty()) {
6932 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
6935 auto ivarCount = ivars.size();
6936 ivars.finishAndAddTo(ivarList);
6937 ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount);
6939 const char *Prefix = "_OBJC_$_INSTANCE_VARIABLES_
";
6940 llvm::GlobalVariable *GV = finishAndCreateGlobal(
6941 ivarList, Prefix + OID->getObjCRuntimeNameAsString(), CGM);
6942 CGM.addCompilerUsedGlobal(GV);
6947CGObjCNonFragileABIMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
6948 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
6950 assert(!PD->isNonRuntimeProtocol() &&
6951 "attempting to GetOrEmit a non-runtime protocol
");
6953 // We use the initializer as a marker of whether this is a forward
6954 // reference or not. At module finalization we add the empty
6955 // contents for protocols which were referenced but never defined.
6956 llvm::SmallString<64> Protocol;
6957 llvm::raw_svector_ostream(Protocol)
6958 << "_OBJC_PROTOCOL_$_
" << PD->getObjCRuntimeNameAsString();
6960 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
6961 false, llvm::GlobalValue::ExternalLinkage,
6963 if (!CGM.getTriple().isOSBinFormatMachO())
6964 Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol));
6991CGObjCNonFragileABIMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
6992 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
6994 // Early exit if a defining object has already been generated.
6995 if (Entry && Entry->hasInitializer())
6998 // Use the protocol definition, if there is one.
6999 assert(PD->hasDefinition() &&
7000 "emitting protocol metadata without definition
");
7001 PD = PD->getDefinition();
7003 auto methodLists = ProtocolMethodLists::get(PD);
7005 ConstantInitBuilder builder(CGM);
7006 auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy);
7009 values.addNullPointer(ObjCTypes.ObjectPtrTy);
7010 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
7011 values.add(EmitProtocolList("_OBJC_$_PROTOCOL_REFS_
" +
7012 PD->getObjCRuntimeNameAsString(),
7013 PD->protocol_begin(), PD->protocol_end()));
7014 values.add(methodLists.emitMethodList(
7015 this, PD, ProtocolMethodLists::RequiredInstanceMethods));
7016 values.add(methodLists.emitMethodList(
7017 this, PD, ProtocolMethodLists::RequiredClassMethods));
7018 values.add(methodLists.emitMethodList(
7019 this, PD, ProtocolMethodLists::OptionalInstanceMethods));
7020 values.add(methodLists.emitMethodList(
7021 this, PD, ProtocolMethodLists::OptionalClassMethods));
7023 EmitPropertyList("_OBJC_$_PROP_LIST_
" + PD->getObjCRuntimeNameAsString(),
7024 nullptr, PD, ObjCTypes, false));
7026 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
7027 values.addInt(ObjCTypes.IntTy, Size);
7028 values.addInt(ObjCTypes.IntTy, 0);
7029 values.add(EmitProtocolMethodTypes(
7030 "_OBJC_$_PROTOCOL_METHOD_TYPES_
" + PD->getObjCRuntimeNameAsString(),
7031 methodLists.emitExtendedTypesArray(this), ObjCTypes));
7033 // const char *demangledName;
7034 values.addNullPointer(ObjCTypes.Int8PtrTy);
7036 values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_
" +
7037 PD->getObjCRuntimeNameAsString(),
7038 nullptr, PD, ObjCTypes, true));
7041 // Already created, fix the linkage and update the initializer.
7042 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
7043 values.finishAndSetAsInitializer(Entry);
7045 llvm::SmallString<64> symbolName;
7046 llvm::raw_svector_ostream(symbolName)
7047 << "_OBJC_PROTOCOL_$_
" << PD->getObjCRuntimeNameAsString();
7049 Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(),
7051 llvm::GlobalValue::WeakAnyLinkage);
7052 if (!CGM.getTriple().isOSBinFormatMachO())
7053 Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName));
7055 Protocols[PD->getIdentifier()] = Entry;
7057 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
7058 CGM.addUsedGlobal(Entry);
7060 // Use this protocol meta-data to build protocol list table in section
7061 // __DATA, __objc_protolist
7062 llvm::SmallString<64> ProtocolRef;
7063 llvm::raw_svector_ostream(ProtocolRef)
7064 << "_OBJC_LABEL_PROTOCOL_$_
" << PD->getObjCRuntimeNameAsString();
7066 llvm::GlobalVariable *PTGV = new llvm::GlobalVariable(
7067 CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy, false,
7068 llvm::GlobalValue::WeakAnyLinkage, Entry, ProtocolRef);
7069 if (!CGM.getTriple().isOSBinFormatMachO())
7070 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef));
7072 CGM.getDataLayout().getABITypeAlign(ObjCTypes.ProtocolnfABIPtrTy));
7074 GetSectionName("__objc_protolist
", "coalesced,no_dead_strip
"));
7075 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
7076 CGM.addUsedGlobal(PTGV);
7088llvm::Constant *CGObjCNonFragileABIMac::EmitProtocolList(
7089 Twine Name, ObjCProtocolDecl::protocol_iterator begin,
7090 ObjCProtocolDecl::protocol_iterator end) {
7091 // Just return null for empty protocol lists
7092 auto Protocols = GetRuntimeProtocolList(begin, end);
7093 if (Protocols.empty())
7094 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
7096 SmallVector<llvm::Constant *, 16> ProtocolRefs;
7097 ProtocolRefs.reserve(Protocols.size());
7099 for (const auto *PD : Protocols)
7100 ProtocolRefs.push_back(GetProtocolRef(PD));
7102 // If all of the protocols in the protocol list are objc_non_runtime_protocol
7104 if (ProtocolRefs.size() == 0)
7105 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
7107 // FIXME: We shouldn't need to do this lookup here, should we?
7108 SmallString<256> TmpName;
7109 Name.toVector(TmpName);
7110 llvm::GlobalVariable *GV =
7111 CGM.getModule().getGlobalVariable(TmpName.str(), true);
7115 ConstantInitBuilder builder(CGM);
7116 auto values = builder.beginStruct();
7117 auto countSlot = values.addPlaceholder();
7119 // A null-terminated array of protocols.
7120 auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy);
7121 for (auto const &proto : ProtocolRefs)
7123 auto count = array.size();
7124 array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy);
7126 array.finishAndAddTo(values);
7127 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
7129 GV = finishAndCreateGlobal(values, Name, CGM);
7130 CGM.addCompilerUsedGlobal(GV);
7140LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
7141 CodeGen::CodeGenFunction &CGF, QualType ObjectTy, llvm::Value *BaseValue,
7142 const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) {
7143 ObjCInterfaceDecl *ID = ObjectTy->castAs<ObjCObjectType>()->getInterface();
7144 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
7145 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
7150CGObjCNonFragileABIMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
7151 const ObjCInterfaceDecl *Interface,
7152 const ObjCIvarDecl *Ivar) {
7153 llvm::Value *IvarOffsetValue;
7154 if (isClassLayoutKnownStatically(Interface)) {
7155 IvarOffsetValue = llvm::ConstantInt::get(
7156 ObjCTypes.IvarOffsetVarTy,
7157 ComputeIvarBaseOffset(CGM, Interface->getImplementation(), Ivar));
7159 llvm::GlobalVariable *GV = ObjCIvarOffsetVariable(Interface, Ivar);
7160 IvarOffsetValue = CGF.Builder.CreateAlignedLoad(GV->getValueType(), GV,
7161 CGF.getSizeAlign(), "ivar
");
7162 if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
7163 cast<llvm::LoadInst>(IvarOffsetValue)
7164 ->setMetadata(llvm::LLVMContext::MD_invariant_load,
7165 llvm::MDNode::get(VMContext, {}));
7168 // This could be 32bit int or 64bit integer depending on the architecture.
7169 // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
7170 // as this is what caller always expects.
7171 if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
7172 IvarOffsetValue = CGF.Builder.CreateIntCast(
7173 IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv
");
7174 return IvarOffsetValue;
7177static void appendSelectorForMessageRefTable(std::string &buffer,
7178 Selector selector) {
7179 if (selector.isUnarySelector()) {
7180 buffer += selector.getNameForSlot(0);
7184 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
7185 buffer += selector.getNameForSlot(i);
7200RValue CGObjCNonFragileABIMac::EmitVTableMessageSend(
7201 CodeGenFunction &CGF, ReturnValueSlot returnSlot, QualType resultType,
7202 Selector selector, llvm::Value *arg0, QualType arg0Type, bool isSuper,
7203 const CallArgList &formalArgs, const ObjCMethodDecl *method) {
7204 // Compute the actual arguments.
7207 // First argument: the receiver / super-call structure.
7209 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
7210 args.add(RValue::get(arg0), arg0Type);
7212 // Second argument: a pointer to the message ref structure. Leave
7213 // the actual argument value blank for now.
7214 args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy);
7216 llvm::append_range(args, formalArgs);
7218 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
7220 NullReturnState nullReturn;
7222 // Find the function to call and the mangled name for the message
7223 // ref structure. Using a different mangled name wouldn't actually
7224 // be a problem; it would just be a waste.
7226 // The runtime currently never uses vtable dispatch for anything
7227 // except normal, non-super message-sends.
7228 // FIXME: don't use this for that.
7229 llvm::FunctionCallee fn = nullptr;
7230 std::string messageRefName("_
");
7231 if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
7233 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
7234 messageRefName += "objc_msgSendSuper2_stret_fixup
";
7236 nullReturn.init(CGF, arg0);
7237 fn = ObjCTypes.getMessageSendStretFixupFn();
7238 messageRefName += "objc_msgSend_stret_fixup
";
7240 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
7241 fn = ObjCTypes.getMessageSendFpretFixupFn();
7242 messageRefName += "objc_msgSend_fpret_fixup
";
7245 fn = ObjCTypes.getMessageSendSuper2FixupFn();
7246 messageRefName += "objc_msgSendSuper2_fixup
";
7248 fn = ObjCTypes.getMessageSendFixupFn();
7249 messageRefName += "objc_msgSend_fixup
";
7252 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend
");
7253 messageRefName += '_';
7255 // Append the selector name, except use underscores anywhere we
7256 // would have used colons.
7257 appendSelectorForMessageRefTable(messageRefName, selector);
7259 llvm::GlobalVariable *messageRef =
7260 CGM.getModule().getGlobalVariable(messageRefName);
7262 // Build the message ref structure.
7263 ConstantInitBuilder builder(CGM);
7264 auto values = builder.beginStruct();
7265 values.add(cast<llvm::Constant>(fn.getCallee()));
7266 values.add(GetMethodVarName(selector));
7267 messageRef = values.finishAndCreateGlobal(
7268 messageRefName, CharUnits::fromQuantity(16),
7269 /*constant*/ false, llvm::GlobalValue::WeakAnyLinkage);
7270 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
7271 messageRef->setSection(GetSectionName("__objc_msgrefs
", "coalesced
"));
7274 bool requiresnullCheck = false;
7275 if (CGM.getLangOpts().ObjCAutoRefCount && method)
7276 for (const auto *ParamDecl : method->parameters()) {
7277 if (ParamDecl->isDestroyedInCallee()) {
7278 if (!nullReturn.NullBB)
7279 nullReturn.init(CGF, arg0);
7280 requiresnullCheck = true;
7286 Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy),
7287 ObjCTypes.MessageRefTy, CGF.getPointerAlign());
7289 // Update the message ref argument.
7290 args[1].setRValue(RValue::get(mref, CGF));
7292 // Load the function to call from the message ref table.
7293 Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0);
7294 llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn
");
7296 calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType);
7297 CGCallee callee(CGCalleeInfo(), calleePtr);
7299 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
7300 return nullReturn.complete(CGF, returnSlot, result, resultType, formalArgs,
7301 requiresnullCheck ? method : nullptr);
7305CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSend(
7306 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
7307 Selector Sel, llvm::Value *Receiver, const CallArgList &CallArgs,
7308 const ObjCInterfaceDecl *Class, const ObjCMethodDecl *Method) {
7309 return isVTableDispatchedSelector(Sel)
7310 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel, Receiver,
7311 CGF.getContext().getObjCIdType(), false,
7313 : EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
7314 CGF.getContext().getObjCIdType(), false,
7315 CallArgs, Method, Class, ObjCTypes);
7319CGObjCNonFragileABIMac::GetClassGlobal(const ObjCInterfaceDecl *ID,
7321 ForDefinition_t isForDefinition) {
7323 (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix());
7324 return GetClassGlobal((prefix + ID->getObjCRuntimeNameAsString()).str(),
7325 isForDefinition, ID->isWeakImported(),
7327 CGM.getTriple().isOSBinFormatCOFF() &&
7328 ID->hasAttr<DLLImportAttr>());
7332CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name,
7333 ForDefinition_t IsForDefinition,
7334 bool Weak, bool DLLImport) {
7335 llvm::GlobalValue::LinkageTypes L =
7336 Weak ? llvm::GlobalValue::ExternalWeakLinkage
7337 : llvm::GlobalValue::ExternalLinkage;
7339 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
7340 if (!GV || GV->getValueType() != ObjCTypes.ClassnfABITy) {
7341 auto *NewGV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false, L,
7345 NewGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
7348 GV->replaceAllUsesWith(NewGV);
7349 GV->eraseFromParent();
7352 CGM.getModule().insertGlobalVariable(GV);
7355 assert(GV->getLinkage() == L);
7360CGObjCNonFragileABIMac::GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID) {
7361 llvm::Constant *ClassGV =
7362 GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
7364 if (!ID->hasAttr<ObjCClassStubAttr>())
7367 ClassGV = llvm::ConstantExpr::getPointerCast(ClassGV, ObjCTypes.Int8PtrTy);
7369 // Stub classes are pointer-aligned. Classrefs pointing at stub classes
7370 // must set the least significant bit set to 1.
7371 auto *Idx = llvm::ConstantInt::get(CGM.Int32Ty, 1);
7372 return llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, ClassGV, Idx);
7376CGObjCNonFragileABIMac::EmitLoadOfClassRef(CodeGenFunction &CGF,
7377 const ObjCInterfaceDecl *ID,
7378 llvm::GlobalVariable *Entry) {
7379 if (ID && ID->hasAttr<ObjCClassStubAttr>()) {
7380 // Classrefs pointing at Objective-C stub classes must be loaded by calling
7381 // a special runtime function.
7382 return CGF.EmitRuntimeCall(ObjCTypes.getLoadClassrefFn(), Entry,
7383 "load_classref_result
");
7386 CharUnits Align = CGF.getPointerAlign();
7387 return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry, Align);
7390llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(
7391 CodeGenFunction &CGF, IdentifierInfo *II, const ObjCInterfaceDecl *ID) {
7392 llvm::GlobalVariable *&Entry = ClassReferences[II];
7395 llvm::Constant *ClassGV;
7397 ClassGV = GetClassGlobalForClassRef(ID);
7399 ClassGV = GetClassGlobal((getClassSymbolPrefix() + II->getName()).str(),
7401 assert(ClassGV->getType() == ObjCTypes.ClassnfABIPtrTy &&
7402 "classref was emitted with the wrong
type?
");
7405 std::string SectionName =
7406 GetSectionName("__objc_classrefs
", "regular,no_dead_strip
");
7407 Entry = new llvm::GlobalVariable(
7408 CGM.getModule(), ClassGV->getType(), false,
7409 getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV,
7410 "OBJC_CLASSLIST_REFERENCES_$_
");
7411 Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
7412 if (!ID || !ID->hasAttr<ObjCClassStubAttr>())
7413 Entry->setSection(SectionName);
7415 CGM.addCompilerUsedGlobal(Entry);
7418 return EmitLoadOfClassRef(CGF, ID, Entry);
7421llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
7422 const ObjCInterfaceDecl *ID) {
7423 // If the class has the objc_runtime_visible attribute, we need to
7424 // use the Objective-C runtime to get the class.
7425 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
7426 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
7428 return EmitClassRefFromId(CGF, ID->getIdentifier(), ID);
7432CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
7433 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool
");
7434 return EmitClassRefFromId(CGF, II, nullptr);
7438CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
7439 const ObjCInterfaceDecl *ID) {
7440 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
7443 llvm::Constant *ClassGV = GetClassGlobalForClassRef(ID);
7444 std::string SectionName =
7445 GetSectionName("__objc_superrefs
", "regular,no_dead_strip
");
7446 Entry = new llvm::GlobalVariable(CGM.getModule(), ClassGV->getType(), false,
7447 llvm::GlobalValue::PrivateLinkage, ClassGV,
7448 "OBJC_CLASSLIST_SUP_REFS_$_
");
7449 Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
7450 Entry->setSection(SectionName);
7451 CGM.addCompilerUsedGlobal(Entry);
7454 return EmitLoadOfClassRef(CGF, ID, Entry);
7460llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(
7461 CodeGenFunction &CGF, const ObjCInterfaceDecl *ID, bool Weak) {
7462 CharUnits Align = CGF.getPointerAlign();
7463 llvm::GlobalVariable *&Entry = MetaClassReferences[ID->getIdentifier()];
7465 auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition);
7466 std::string SectionName =
7467 GetSectionName("__objc_superrefs
", "regular,no_dead_strip
");
7468 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
7469 false, llvm::GlobalValue::PrivateLinkage,
7470 MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_
");
7471 Entry->setAlignment(Align.getAsAlign());
7472 Entry->setSection(SectionName);
7473 CGM.addCompilerUsedGlobal(Entry);
7476 return CGF.Builder.CreateAlignedLoad(ObjCTypes.ClassnfABIPtrTy, Entry, Align);
7481llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
7482 const ObjCInterfaceDecl *ID) {
7483 if (ID->isWeakImported()) {
7484 auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
7486 assert(!isa<llvm::GlobalVariable>(ClassGV) ||
7487 cast<llvm::GlobalVariable>(ClassGV)->hasExternalWeakLinkage());
7490 return EmitClassRef(CGF, ID);
7496CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSendSuper(
7497 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
7498 Selector Sel, const ObjCInterfaceDecl *Class, bool isCategoryImpl,
7499 llvm::Value *Receiver, bool IsClassMessage,
7500 const CodeGen::CallArgList &CallArgs, const ObjCMethodDecl *Method) {
7502 // Create and init a super structure; this is a (receiver, class)
7503 // pair we will pass to objc_msgSendSuper.
7504 RawAddress ObjCSuper = CGF.CreateTempAlloca(
7505 ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super
");
7507 llvm::Value *ReceiverAsObject =
7508 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
7509 CGF.Builder.CreateStore(ReceiverAsObject,
7510 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
7512 // If this is a class message the metaclass is passed as the target.
7513 llvm::Value *Target;
7515 Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported());
7517 Target = EmitSuperClassRef(CGF, Class);
7519 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
7521 llvm::Type *ClassTy =
7522 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
7523 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
7524 CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
7526 return (isVTableDispatchedSelector(Sel))
7527 ? EmitVTableMessageSend(
7528 CGF, Return, ResultType, Sel, ObjCSuper.getPointer(),
7529 ObjCTypes.SuperPtrCTy, true, CallArgs, Method)
7530 : EmitMessageSend(CGF, Return, ResultType, Sel,
7531 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
7532 true, CallArgs, Method, Class, ObjCTypes);
7535llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
7537 Address Addr = EmitSelectorAddr(Sel);
7539 llvm::LoadInst *LI = CGF.Builder.CreateLoad(Addr);
7540 LI->setMetadata(llvm::LLVMContext::MD_invariant_load,
7541 llvm::MDNode::get(VMContext, {}));
7545ConstantAddress CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) {
7546 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
7547 CharUnits Align = CGM.getPointerAlign();
7549 std::string SectionName =
7550 GetSectionName("__objc_selrefs
", "literal_pointers,no_dead_strip
");
7551 Entry = new llvm::GlobalVariable(
7552 CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
7553 getLinkageTypeForObjCMetadata(CGM, SectionName), GetMethodVarName(Sel),
7554 "OBJC_SELECTOR_REFERENCES_
");
7555 Entry->setExternallyInitialized(true);
7556 Entry->setSection(SectionName);
7557 Entry->setAlignment(Align.getAsAlign());
7558 CGM.addCompilerUsedGlobal(Entry);
7561 return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align);
7567void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
7568 llvm::Value *src, Address dst,
7569 llvm::Value *ivarOffset) {
7570 llvm::Type *SrcTy = src->getType();
7571 if (!isa<llvm::PointerType>(SrcTy)) {
7572 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
7573 assert(Size <= 8 && "does
not support size > 8
");
7574 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7575 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
7576 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7578 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7579 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
7580 ObjCTypes.PtrObjectPtrTy);
7581 llvm::Value *args[] = {src, dstVal, ivarOffset};
7582 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
7588void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
7589 CodeGen::CodeGenFunction &CGF, llvm::Value *src, Address dst) {
7590 llvm::Type *SrcTy = src->getType();
7591 if (!isa<llvm::PointerType>(SrcTy)) {
7592 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
7593 assert(Size <= 8 && "does
not support size > 8
");
7594 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7595 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
7596 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7598 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7599 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
7600 ObjCTypes.PtrObjectPtrTy);
7601 llvm::Value *args[] = {src, dstVal};
7602 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args,
7606void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
7607 CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr,
7608 llvm::Value *Size) {
7609 llvm::Value *args[] = {DestPtr.emitRawPointer(CGF),
7610 SrcPtr.emitRawPointer(CGF), Size};
7611 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
7618CGObjCNonFragileABIMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
7619 Address AddrWeakObj) {
7620 llvm::Type *DestTy = AddrWeakObj.getElementType();
7621 llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast(
7622 AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy);
7623 llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall(
7624 ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread
");
7625 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
7632void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
7633 llvm::Value *src, Address dst) {
7634 llvm::Type *SrcTy = src->getType();
7635 if (!isa<llvm::PointerType>(SrcTy)) {
7636 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
7637 assert(Size <= 8 && "does
not support size > 8
");
7638 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7639 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
7640 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7642 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7643 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
7644 ObjCTypes.PtrObjectPtrTy);
7645 llvm::Value *args[] = {src, dstVal};
7646 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args,
7653void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
7654 llvm::Value *src, Address dst,
7656 llvm::Type *SrcTy = src->getType();
7657 if (!isa<llvm::PointerType>(SrcTy)) {
7658 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
7659 assert(Size <= 8 && "does
not support size > 8
");
7660 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7661 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
7662 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7664 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7665 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
7666 ObjCTypes.PtrObjectPtrTy);
7667 llvm::Value *args[] = {src, dstVal};
7669 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), args,
7672 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), args,
7673 "threadlocalassign
");
7676void CGObjCNonFragileABIMac::EmitSynchronizedStmt(
7677 CodeGen::CodeGenFunction &CGF, const ObjCAtSynchronizedStmt &S) {
7678 EmitAtSynchronizedStmt(CGF, S, ObjCTypes.getSyncEnterFn(),
7679 ObjCTypes.getSyncExitFn());
7682llvm::Constant *CGObjCNonFragileABIMac::GetEHType(QualType T) {
7683 // There's a particular fixed type info for 'id'.
7684 if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
7685 auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id
");
7687 IDEHType = new llvm::GlobalVariable(
7688 CGM.getModule(), ObjCTypes.EHTypeTy, false,
7689 llvm::GlobalValue::ExternalLinkage, nullptr, "OBJC_EHTYPE_id
");
7690 if (CGM.getTriple().isOSBinFormatCOFF())
7691 IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id
"));
7696 // All other types should be Objective-C interface pointer types.
7697 const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
7700 const ObjCInterfaceType *IT = PT->getInterfaceType();
7701 assert(IT && "Invalid
@catch type.
");
7703 return GetInterfaceEHType(IT->getDecl(), NotForDefinition);
7706void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
7707 const ObjCAtTryStmt &S) {
7708 EmitTryCatchStmt(CGF, S, ObjCTypes.getObjCBeginCatchFn(),
7709 ObjCTypes.getObjCEndCatchFn(),
7710 ObjCTypes.getExceptionRethrowFn());
7714void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
7715 const ObjCAtThrowStmt &S,
7716 bool ClearInsertionPoint) {
7717 if (const Expr *ThrowExpr = S.getThrowExpr()) {
7718 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
7719 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
7720 llvm::CallBase *Call =
7721 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception);
7722 Call->setDoesNotReturn();
7724 llvm::CallBase *Call =
7725 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn());
7726 Call->setDoesNotReturn();
7729 CGF.Builder.CreateUnreachable();
7730 if (ClearInsertionPoint)
7731 CGF.Builder.ClearInsertionPoint();
7735CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
7736 ForDefinition_t IsForDefinition) {
7737 llvm::GlobalVariable *&Entry = EHTypeReferences[ID->getIdentifier()];
7738 StringRef ClassName = ID->getObjCRuntimeNameAsString();
7740 // If we don't need a definition, return the entry if found or check
7741 // if we use an external reference.
7742 if (!IsForDefinition) {
7746 // If this type (or a super class) has the __objc_exception__
7747 // attribute, emit an external reference.
7748 if (hasObjCExceptionAttribute(CGM.getContext(), ID)) {
7749 std::string EHTypeName = ("OBJC_EHTYPE_$_
" + ClassName).str();
7750 Entry = new llvm::GlobalVariable(
7751 CGM.getModule(), ObjCTypes.EHTypeTy, false,
7752 llvm::GlobalValue::ExternalLinkage, nullptr, EHTypeName);
7753 CGM.setGVProperties(Entry, ID);
7758 // Otherwise we need to either make a new entry or fill in the initializer.
7759 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition
");
7761 std::string VTableName = "objc_ehtype_vtable
";
7762 auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName);
7764 VTableGV = new llvm::GlobalVariable(
7765 CGM.getModule(), ObjCTypes.Int8PtrTy, false,
7766 llvm::GlobalValue::ExternalLinkage, nullptr, VTableName);
7767 if (CGM.getTriple().isOSBinFormatCOFF())
7768 VTableGV->setDLLStorageClass(getStorage(CGM, VTableName));
7771 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
7772 llvm::Constant *VTablePtr = llvm::ConstantExpr::getInBoundsGetElementPtr(
7773 VTableGV->getValueType(), VTableGV, VTableIdx);
7775 ConstantInitBuilder builder(CGM);
7776 auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
7777 const PointerAuthSchema &TypeInfoSchema =
7778 CGM.getCodeGenOpts().PointerAuth.CXXTypeInfoVTablePointer;
7779 values.addSignedPointer(VTablePtr, TypeInfoSchema, GlobalDecl(), QualType());
7781 values.add(GetClassName(ClassName));
7782 values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition));
7784 llvm::GlobalValue::LinkageTypes L = IsForDefinition
7785 ? llvm::GlobalValue::ExternalLinkage
7786 : llvm::GlobalValue::WeakAnyLinkage;
7788 values.finishAndSetAsInitializer(Entry);
7789 Entry->setAlignment(CGM.getPointerAlign().getAsAlign());
7791 Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_
" + ClassName,
7792 CGM.getPointerAlign(),
7793 /*constant*/ false, L);
7794 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
7795 CGM.setGVProperties(Entry, ID);
7797 assert(Entry->getLinkage() == L);
7799 if (!CGM.getTriple().isOSBinFormatCOFF())
7800 if (ID->getVisibility() == HiddenVisibility)
7801 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
7803 if (IsForDefinition)
7804 if (CGM.getTriple().isOSBinFormatMachO())
7805 Entry->setSection("__DATA,__objc_const
");
7812CodeGen::CGObjCRuntime *
7813CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
7814 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7815 case ObjCRuntime::FragileMacOSX:
7816 return new CGObjCMac(CGM);
7818 case ObjCRuntime::MacOSX:
7819 case ObjCRuntime::iOS:
7820 case ObjCRuntime::WatchOS:
7821 return new CGObjCNonFragileABIMac(CGM);
7823 case ObjCRuntime::GNUstep:
7824 case ObjCRuntime::GCC:
7825 case ObjCRuntime::ObjFW:
7826 llvm_unreachable("these runtimes are
not Mac runtimes
");
7828 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.
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 ObjCConstantStringClass
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 isNonFragile() const
Does this runtime follow the set of implied behaviors for a "non-fragile" ABI?
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.
const FunctionProtoType * T
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::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.