30#include "llvm/ADT/CachedHashString.h"
31#include "llvm/ADT/DenseSet.h"
32#include "llvm/ADT/SetVector.h"
33#include "llvm/ADT/SmallPtrSet.h"
34#include "llvm/ADT/SmallString.h"
35#include "llvm/ADT/UniqueVector.h"
36#include "llvm/IR/DataLayout.h"
37#include "llvm/IR/InlineAsm.h"
38#include "llvm/IR/IntrinsicInst.h"
39#include "llvm/IR/LLVMContext.h"
40#include "llvm/IR/Module.h"
41#include "llvm/Support/ScopedPrinter.h"
42#include "llvm/Support/raw_ostream.h"
46using namespace CodeGen;
53class ObjCCommonTypesHelper {
55 llvm::LLVMContext &VMContext;
65 llvm::FunctionCallee getMessageSendFn()
const {
68 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
69 return CGM.CreateRuntimeFunction(
70 llvm::FunctionType::get(ObjectPtrTy, params,
true),
"objc_msgSend",
71 llvm::AttributeList::get(CGM.getLLVMContext(),
72 llvm::AttributeList::FunctionIndex,
73 llvm::Attribute::NonLazyBind));
81 llvm::FunctionCallee getMessageSendStretFn()
const {
82 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
83 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy,
85 "objc_msgSend_stret");
93 llvm::FunctionCallee getMessageSendFpretFn()
const {
94 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
95 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy,
97 "objc_msgSend_fpret");
105 llvm::FunctionCallee getMessageSendFp2retFn()
const {
106 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
107 llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
108 llvm::Type *resultType =
109 llvm::StructType::get(longDoubleType, longDoubleType);
111 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType,
113 "objc_msgSend_fp2ret");
121 llvm::FunctionCallee getMessageSendSuperFn()
const {
122 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
123 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
125 "objc_msgSendSuper");
132 llvm::FunctionCallee getMessageSendSuperFn2()
const {
133 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
134 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
136 "objc_msgSendSuper2");
143 llvm::FunctionCallee getMessageSendSuperStretFn()
const {
144 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
145 return CGM.CreateRuntimeFunction(
146 llvm::FunctionType::get(CGM.VoidTy, params,
true),
147 "objc_msgSendSuper_stret");
154 llvm::FunctionCallee getMessageSendSuperStretFn2()
const {
155 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
156 return CGM.CreateRuntimeFunction(
157 llvm::FunctionType::get(CGM.VoidTy, params,
true),
158 "objc_msgSendSuper2_stret");
161 llvm::FunctionCallee getMessageSendSuperFpretFn()
const {
163 return getMessageSendSuperFn();
166 llvm::FunctionCallee getMessageSendSuperFpretFn2()
const {
168 return getMessageSendSuperFn2();
175 llvm::IntegerType *ShortTy, *IntTy, *LongTy;
176 llvm::PointerType *Int8PtrTy, *Int8PtrPtrTy;
177 llvm::PointerType *Int8PtrProgramASTy;
178 llvm::Type *IvarOffsetVarTy;
181 llvm::PointerType *ObjectPtrTy;
184 llvm::PointerType *PtrObjectPtrTy;
187 llvm::PointerType *SelectorPtrTy;
192 llvm::Type *ExternalProtocolPtrTy;
195 llvm::Type *getExternalProtocolPtrTy() {
196 if (!ExternalProtocolPtrTy) {
202 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
205 return ExternalProtocolPtrTy;
214 llvm::StructType *SuperTy;
216 llvm::PointerType *SuperPtrTy;
220 llvm::StructType *PropertyTy;
224 llvm::StructType *PropertyListTy;
226 llvm::PointerType *PropertyListPtrTy;
229 llvm::StructType *MethodTy;
234 llvm::PointerType *CachePtrTy;
236 llvm::FunctionCallee getGetPropertyFn() {
245 llvm::FunctionType *FTy =
246 Types.GetFunctionType(
247 Types.arrangeBuiltinFunctionDeclaration(IdType, Params));
251 llvm::FunctionCallee getSetPropertyFn() {
264 llvm::FunctionType *FTy =
265 Types.GetFunctionType(
266 Types.arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Params));
270 llvm::FunctionCallee getOptimizedSetPropertyFn(
bool atomic,
bool copy) {
285 Params.push_back(IdType);
286 Params.push_back(SelType);
287 Params.push_back(IdType);
289 llvm::FunctionType *FTy =
290 Types.GetFunctionType(
291 Types.arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Params));
294 name =
"objc_setProperty_atomic_copy";
295 else if (atomic && !copy)
296 name =
"objc_setProperty_atomic";
297 else if (!atomic && copy)
298 name =
"objc_setProperty_nonatomic_copy";
300 name =
"objc_setProperty_nonatomic";
305 llvm::FunctionCallee getCopyStructFn() {
313 Params.push_back(Ctx.
BoolTy);
314 Params.push_back(Ctx.
BoolTy);
315 llvm::FunctionType *FTy =
316 Types.GetFunctionType(
317 Types.arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Params));
325 llvm::FunctionCallee getCppAtomicObjectFunction() {
333 llvm::FunctionType *FTy =
334 Types.GetFunctionType(
335 Types.arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Params));
339 llvm::FunctionCallee getEnumerationMutationFn() {
345 llvm::FunctionType *FTy =
346 Types.GetFunctionType(
347 Types.arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Params));
351 llvm::FunctionCallee getLookUpClassFn() {
358 llvm::FunctionType *FTy =
359 Types.GetFunctionType(Types.arrangeBuiltinFunctionDeclaration(
366 llvm::FunctionCallee getGcReadWeakFn() {
368 llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
369 llvm::FunctionType *FTy =
370 llvm::FunctionType::get(ObjectPtrTy, args,
false);
375 llvm::FunctionCallee getGcAssignWeakFn() {
377 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
378 llvm::FunctionType *FTy =
379 llvm::FunctionType::get(ObjectPtrTy, args,
false);
384 llvm::FunctionCallee getGcAssignGlobalFn() {
386 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
387 llvm::FunctionType *FTy =
388 llvm::FunctionType::get(ObjectPtrTy, args,
false);
393 llvm::FunctionCallee getGcAssignThreadLocalFn() {
395 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
396 llvm::FunctionType *FTy =
397 llvm::FunctionType::get(ObjectPtrTy, args,
false);
402 llvm::FunctionCallee getGcAssignIvarFn() {
404 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
406 llvm::FunctionType *FTy =
407 llvm::FunctionType::get(ObjectPtrTy, args,
false);
412 llvm::FunctionCallee GcMemmoveCollectableFn() {
414 llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
415 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args,
false);
420 llvm::FunctionCallee getGcAssignStrongCastFn() {
422 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
423 llvm::FunctionType *FTy =
424 llvm::FunctionType::get(ObjectPtrTy, args,
false);
429 llvm::FunctionCallee getExceptionThrowFn() {
431 llvm::Type *args[] = { ObjectPtrTy };
432 llvm::FunctionType *FTy =
433 llvm::FunctionType::get(CGM.
VoidTy, args,
false);
438 llvm::FunctionCallee getExceptionRethrowFn() {
440 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.
VoidTy,
false);
445 llvm::FunctionCallee getSyncEnterFn() {
447 llvm::Type *args[] = { ObjectPtrTy };
448 llvm::FunctionType *FTy =
449 llvm::FunctionType::get(CGM.
IntTy, args,
false);
454 llvm::FunctionCallee getSyncExitFn() {
456 llvm::Type *args[] = { ObjectPtrTy };
457 llvm::FunctionType *FTy =
458 llvm::FunctionType::get(CGM.
IntTy, args,
false);
462 llvm::FunctionCallee getSendFn(
bool IsSuper)
const {
463 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
466 llvm::FunctionCallee getSendFn2(
bool IsSuper)
const {
467 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
470 llvm::FunctionCallee getSendStretFn(
bool IsSuper)
const {
471 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
474 llvm::FunctionCallee getSendStretFn2(
bool IsSuper)
const {
475 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
478 llvm::FunctionCallee getSendFpretFn(
bool IsSuper)
const {
479 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
482 llvm::FunctionCallee getSendFpretFn2(
bool IsSuper)
const {
483 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
486 llvm::FunctionCallee getSendFp2retFn(
bool IsSuper)
const {
487 return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
490 llvm::FunctionCallee getSendFp2RetFn2(
bool IsSuper)
const {
491 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
499class ObjCTypesHelper :
public ObjCCommonTypesHelper {
502 llvm::StructType *SymtabTy;
504 llvm::PointerType *SymtabPtrTy;
506 llvm::StructType *ModuleTy;
509 llvm::StructType *ProtocolTy;
511 llvm::PointerType *ProtocolPtrTy;
514 llvm::StructType *ProtocolExtensionTy;
517 llvm::PointerType *ProtocolExtensionPtrTy;
520 llvm::StructType *MethodDescriptionTy;
523 llvm::StructType *MethodDescriptionListTy;
526 llvm::PointerType *MethodDescriptionListPtrTy;
528 llvm::StructType *ProtocolListTy;
530 llvm::PointerType *ProtocolListPtrTy;
532 llvm::StructType *CategoryTy;
534 llvm::StructType *ClassTy;
536 llvm::PointerType *ClassPtrTy;
538 llvm::StructType *ClassExtensionTy;
540 llvm::PointerType *ClassExtensionPtrTy;
542 llvm::StructType *IvarTy;
544 llvm::StructType *IvarListTy;
546 llvm::PointerType *IvarListPtrTy;
548 llvm::StructType *MethodListTy;
550 llvm::PointerType *MethodListPtrTy;
553 llvm::StructType *ExceptionDataTy;
556 llvm::FunctionCallee getExceptionTryEnterFn() {
557 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
559 llvm::FunctionType::get(CGM.
VoidTy, params,
false),
560 "objc_exception_try_enter");
564 llvm::FunctionCallee getExceptionTryExitFn() {
565 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
567 llvm::FunctionType::get(CGM.
VoidTy, params,
false),
568 "objc_exception_try_exit");
572 llvm::FunctionCallee getExceptionExtractFn() {
573 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
576 "objc_exception_extract");
580 llvm::FunctionCallee getExceptionMatchFn() {
581 llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
583 llvm::FunctionType::get(CGM.
Int32Ty, params,
false),
584 "objc_exception_match");
588 llvm::FunctionCallee getSetJmpFn() {
590 llvm::Type *params[] = { CGM.
Int32Ty->getPointerTo() };
592 llvm::FunctionType::get(CGM.
Int32Ty, params,
false),
"_setjmp",
594 llvm::AttributeList::FunctionIndex,
595 llvm::Attribute::NonLazyBind));
604class ObjCNonFragileABITypesHelper :
public ObjCCommonTypesHelper {
607 llvm::StructType *MethodListnfABITy;
610 llvm::PointerType *MethodListnfABIPtrTy;
613 llvm::StructType *ProtocolnfABITy;
616 llvm::PointerType *ProtocolnfABIPtrTy;
619 llvm::StructType *ProtocolListnfABITy;
622 llvm::PointerType *ProtocolListnfABIPtrTy;
625 llvm::StructType *ClassnfABITy;
628 llvm::PointerType *ClassnfABIPtrTy;
631 llvm::StructType *IvarnfABITy;
634 llvm::StructType *IvarListnfABITy;
637 llvm::PointerType *IvarListnfABIPtrTy;
640 llvm::StructType *ClassRonfABITy;
643 llvm::PointerType *ImpnfABITy;
646 llvm::StructType *CategorynfABITy;
655 llvm::StructType *MessageRefTy;
660 llvm::Type *MessageRefPtrTy;
669 llvm::StructType *SuperMessageRefTy;
672 llvm::PointerType *SuperMessageRefPtrTy;
674 llvm::FunctionCallee getMessageSendFixupFn() {
676 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
679 "objc_msgSend_fixup");
682 llvm::FunctionCallee getMessageSendFpretFixupFn() {
684 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
687 "objc_msgSend_fpret_fixup");
690 llvm::FunctionCallee getMessageSendStretFixupFn() {
692 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
695 "objc_msgSend_stret_fixup");
698 llvm::FunctionCallee getMessageSendSuper2FixupFn() {
701 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
704 "objc_msgSendSuper2_fixup");
707 llvm::FunctionCallee getMessageSendSuper2StretFixupFn() {
710 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
713 "objc_msgSendSuper2_stret_fixup");
716 llvm::FunctionCallee getObjCEndCatchFn() {
721 llvm::FunctionCallee getObjCBeginCatchFn() {
722 llvm::Type *params[] = { Int8PtrTy };
733 llvm::FunctionCallee getLoadClassrefFn()
const {
739 llvm::Type *params[] = { Int8PtrPtrTy };
741 llvm::AttributeSet AS = llvm::AttributeSet::get(
C, {
742 llvm::Attribute::get(
C, llvm::Attribute::NonLazyBind),
743 llvm::Attribute::getWithMemoryEffects(
C, llvm::MemoryEffects::none()),
744 llvm::Attribute::get(
C, llvm::Attribute::NoUnwind),
747 llvm::FunctionType::get(ClassnfABIPtrTy, params,
false),
750 llvm::AttributeList::FunctionIndex, AS));
751 if (!CGM.
getTriple().isOSBinFormatCOFF())
752 cast<llvm::Function>(F.getCallee())->setLinkage(
753 llvm::Function::ExternalWeakLinkage);
758 llvm::StructType *EHTypeTy;
759 llvm::Type *EHTypePtrTy;
764enum class ObjCLabelType {
777 SKIP_SCAN(
unsigned _skip = 0,
unsigned _scan = 0)
778 : skip(_skip), scan(_scan) {}
785 enum BLOCK_LAYOUT_OPCODE {
792 BLOCK_LAYOUT_OPERATOR = 0,
798 BLOCK_LAYOUT_NON_OBJECT_BYTES = 1,
803 BLOCK_LAYOUT_NON_OBJECT_WORDS = 2,
807 BLOCK_LAYOUT_STRONG = 3,
810 BLOCK_LAYOUT_BYREF = 4,
814 BLOCK_LAYOUT_WEAK = 5,
818 BLOCK_LAYOUT_UNRETAINED = 6
835 enum BLOCK_LAYOUT_OPCODE opcode;
838 RUN_SKIP(
enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
841 : opcode(
Opcode), block_var_bytepos(BytePos), block_var_size(
Size) {}
845 return block_var_bytepos <
b.block_var_bytepos;
850 llvm::LLVMContext &VMContext;
859 llvm::SetVector<IdentifierInfo*> LazySymbols;
865 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
868 llvm::StringMap<llvm::GlobalVariable*> ClassNames;
871 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
878 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
882 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
886 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> DirectMethodDefinitions;
889 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
892 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
895 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
900 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
926 llvm::WeakTrackingVH ConstantStringClassRef;
929 llvm::StructType *NSConstantStringType =
nullptr;
931 llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap;
935 llvm::Constant *GetMethodVarName(
Selector Sel);
943 bool Extended =
false);
944 llvm::Constant *GetMethodVarType(
const FieldDecl *D);
952 const Decl *Container);
957 llvm::Constant *GetClassName(StringRef RuntimeName);
971 bool forStrongLayout,
977 return BuildIvarLayout(OI, beginOffset, endOffset,
true,
false);
984 return BuildIvarLayout(OI, beginOffset, endOffset,
false,
hasMRCWeakIvars);
989 void UpdateRunSkipBlockVars(
bool IsByref,
994 void BuildRCBlockVarRecordLayout(
const RecordType *RT,
996 bool ByrefLayout=
false);
998 void BuildRCRecordLayout(
const llvm::StructLayout *RecLayout,
1006 llvm::Constant *getBitmapBlockLayout(
bool ComputeByrefLayout);
1011 const ObjCCommonTypesHelper &ObjCTypes);
1015 llvm::Constant *EmitPropertyList(Twine Name,
1016 const Decl *Container,
1018 const ObjCCommonTypesHelper &ObjCTypes,
1019 bool IsClassProperty);
1023 llvm::Constant *EmitProtocolMethodTypes(Twine Name,
1025 const ObjCCommonTypesHelper &ObjCTypes);
1036 ObjCCommonTypesHelper &ObjCTypes);
1038 std::string GetSectionName(StringRef Section, StringRef MachOAttributes);
1055 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
1059 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
1060 llvm::Constant *
Init,
1064 llvm::GlobalVariable *CreateCStringLiteral(StringRef Name,
1065 ObjCLabelType LabelType,
1066 bool ForceNonFragileABI =
false,
1067 bool NullTerminate =
true);
1080 const ObjCCommonTypesHelper &ObjCTypes);
1084 void EmitImageInfo();
1090 bool isNonFragileABI()
const {
1091 return ObjCABI == 2;
1113 virtual llvm::Constant *GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD)=0;
1115 virtual llvm::Constant *getNSConstantStringClassRef() = 0;
1133enum class MethodListType {
1134 CategoryInstanceMethods,
1135 CategoryClassMethods,
1138 ProtocolInstanceMethods,
1139 ProtocolClassMethods,
1140 OptionalProtocolInstanceMethods,
1141 OptionalProtocolClassMethods,
1146class ProtocolMethodLists {
1149 RequiredInstanceMethods,
1150 RequiredClassMethods,
1151 OptionalInstanceMethods,
1152 OptionalClassMethods
1155 NumProtocolMethodLists = 4
1158 static MethodListType getMethodListKind(Kind kind) {
1160 case RequiredInstanceMethods:
1161 return MethodListType::ProtocolInstanceMethods;
1162 case RequiredClassMethods:
1163 return MethodListType::ProtocolClassMethods;
1164 case OptionalInstanceMethods:
1165 return MethodListType::OptionalProtocolInstanceMethods;
1166 case OptionalClassMethods:
1167 return MethodListType::OptionalProtocolClassMethods;
1169 llvm_unreachable(
"bad kind");
1175 ProtocolMethodLists result;
1177 for (
auto *MD : PD->
methods()) {
1178 size_t index = (2 *
size_t(MD->isOptional()))
1179 + (
size_t(MD->isClassMethod()));
1180 result.Methods[index].push_back(MD);
1186 template <
class Self>
1197 for (
auto &list : Methods) {
1198 for (
auto MD : list) {
1199 result.push_back(self->GetMethodVarType(MD,
true));
1206 template <
class Self>
1210 getMethodListKind(kind), Methods[kind]);
1216class CGObjCMac :
public CGObjCCommonMac {
1218 friend ProtocolMethodLists;
1220 ObjCTypesHelper ObjCTypes;
1224 void EmitModuleInfo();
1228 llvm::Constant *EmitModuleSymbols();
1232 void FinishModule();
1250 llvm::Value *EmitNSAutoreleasePoolClassRef(
CodeGenFunction &CGF)
override;
1271 llvm::Constant *Protocols,
1282 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1302 const ProtocolMethodLists &methodLists);
1306 llvm::Constant *EmitProtocolList(Twine Name,
1318 llvm::Constant *getNSConstantStringClassRef()
override;
1320 llvm::Function *ModuleInitFunction()
override;
1325 Selector Sel, llvm::Value *Receiver,
1334 bool isCategoryImpl, llvm::Value *Receiver,
1349 llvm::Constant *GetEHType(
QualType T)
override;
1360 llvm::FunctionCallee GetPropertyGetFunction()
override;
1361 llvm::FunctionCallee GetPropertySetFunction()
override;
1362 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
1363 bool copy)
override;
1364 llvm::FunctionCallee GetGetStructFunction()
override;
1365 llvm::FunctionCallee GetSetStructFunction()
override;
1366 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override;
1367 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override;
1368 llvm::FunctionCallee EnumerationMutationFunction()
override;
1376 bool ClearInsertionPoint=
true)
override;
1378 Address AddrWeakObj)
override;
1380 llvm::Value *src,
Address dst)
override;
1382 llvm::Value *src,
Address dest,
1383 bool threadlocal =
false)
override;
1385 llvm::Value *src,
Address dest,
1386 llvm::Value *ivarOffset)
override;
1388 llvm::Value *src,
Address dest)
override;
1391 llvm::Value *size)
override;
1395 unsigned CVRQualifiers)
override;
1401class CGObjCNonFragileABIMac :
public CGObjCCommonMac {
1403 friend ProtocolMethodLists;
1404 ObjCNonFragileABITypesHelper ObjCTypes;
1405 llvm::GlobalVariable* ObjCEmptyCacheVar;
1406 llvm::Constant* ObjCEmptyVtableVar;
1409 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
1412 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
1415 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
1422 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1426 bool isVTableDispatchedSelector(
Selector Sel);
1430 void FinishNonFragileABIModule();
1435 StringRef SymbolName, StringRef SectionName);
1437 llvm::GlobalVariable * BuildClassRoTInitializer(
unsigned flags,
1438 unsigned InstanceStart,
1439 unsigned InstanceSize,
1443 llvm::Constant *IsAGV,
1444 llvm::Constant *SuperClassGV,
1445 llvm::Constant *ClassRoGV,
1454 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1466 unsigned long int offset);
1481 llvm::Constant *EmitProtocolList(Twine Name,
1489 llvm::Value *Receiver,
1497 llvm::Constant *GetClassGlobal(StringRef Name,
1499 bool Weak =
false,
bool DLLImport =
false);
1508 llvm::GlobalVariable *Entry);
1519 llvm::Value *EmitNSAutoreleasePoolClassRef(
CodeGenFunction &CGF)
override;
1534 llvm::GlobalVariable * ObjCIvarOffsetVariable(
1548 StringRef getMetaclassSymbolPrefix()
const {
return "OBJC_METACLASS_$_"; }
1550 StringRef getClassSymbolPrefix()
const {
return "OBJC_CLASS_$_"; }
1553 uint32_t &InstanceStart,
1554 uint32_t &InstanceSize);
1569 bool ImplementationIsNonLazy(
const ObjCImplDecl *OD)
const;
1588 dyn_cast_or_null<ObjCMethodDecl>(CGF.
CurFuncDecl))
1589 if (MD->isInstanceMethod() && !MD->isDirectMethod())
1598 for (;
ID;
ID =
ID->getSuperClass()) {
1601 if (
ID->getIdentifier()->getName() ==
"NSObject")
1606 if (!
ID->getImplementation())
1615 llvm::Constant *getNSConstantStringClassRef()
override;
1617 llvm::Function *ModuleInitFunction()
override;
1622 llvm::Value *Receiver,
1631 bool isCategoryImpl, llvm::Value *Receiver,
1639 {
return EmitSelector(CGF, Sel); }
1641 {
return EmitSelectorAddr(Sel); }
1647 {
return EmitSelector(CGF, Method->
getSelector()); }
1658 llvm::Constant *GetEHType(
QualType T)
override;
1660 llvm::FunctionCallee GetPropertyGetFunction()
override {
1661 return ObjCTypes.getGetPropertyFn();
1663 llvm::FunctionCallee GetPropertySetFunction()
override {
1664 return ObjCTypes.getSetPropertyFn();
1667 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
1668 bool copy)
override {
1669 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1672 llvm::FunctionCallee GetSetStructFunction()
override {
1673 return ObjCTypes.getCopyStructFn();
1676 llvm::FunctionCallee GetGetStructFunction()
override {
1677 return ObjCTypes.getCopyStructFn();
1680 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override {
1681 return ObjCTypes.getCppAtomicObjectFunction();
1684 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override {
1685 return ObjCTypes.getCppAtomicObjectFunction();
1688 llvm::FunctionCallee EnumerationMutationFunction()
override {
1689 return ObjCTypes.getEnumerationMutationFn();
1697 bool ClearInsertionPoint=
true)
override;
1699 Address AddrWeakObj)
override;
1701 llvm::Value *src,
Address edst)
override;
1703 llvm::Value *src,
Address dest,
1704 bool threadlocal =
false)
override;
1706 llvm::Value *src,
Address dest,
1707 llvm::Value *ivarOffset)
override;
1709 llvm::Value *src,
Address dest)
override;
1712 llvm::Value *size)
override;
1715 unsigned CVRQualifiers)
override;
1723struct NullReturnState {
1724 llvm::BasicBlock *NullBB =
nullptr;
1725 NullReturnState() =
default;
1737 llvm::Value *isNull = CGF.
Builder.CreateIsNull(receiver);
1738 CGF.
Builder.CreateCondBr(isNull, NullBB, callBB);
1753 if (!NullBB)
return result;
1757 llvm::BasicBlock *contBB =
nullptr;
1760 llvm::BasicBlock *callBB = CGF.
Builder.GetInsertBlock();
1775 assert(CGF.
Builder.GetInsertBlock() == NullBB);
1795 llvm::PHINode *phi = CGF.
Builder.CreatePHI(null->getType(), 2);
1797 phi->addIncoming(null, NullBB);
1806 assert(result.
isAggregate() &&
"null init of non-aggregate result?");
1815 CodeGenFunction::ComplexPairTy callResult = result.
getComplexVal();
1818 llvm::Type *scalarTy = callResult.first->getType();
1819 llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
1822 llvm::PHINode *real = CGF.
Builder.CreatePHI(scalarTy, 2);
1823 real->addIncoming(callResult.first, callBB);
1824 real->addIncoming(scalarZero, NullBB);
1825 llvm::PHINode *imag = CGF.
Builder.CreatePHI(scalarTy, 2);
1826 imag->addIncoming(callResult.second, callBB);
1827 imag->addIncoming(scalarZero, NullBB);
1838 llvm::GlobalVariable *
C,
unsigned idx0,
1840 llvm::Value *Idxs[] = {
1841 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1842 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
1844 return llvm::ConstantExpr::getGetElementPtr(
C->getValueType(),
C, Idxs);
1851 if (OID->
hasAttr<ObjCExceptionAttr>())
1858static llvm::GlobalValue::LinkageTypes
1860 if (CGM.
getTriple().isOSBinFormatMachO() &&
1861 (Section.empty() || Section.starts_with(
"__DATA")))
1862 return llvm::GlobalValue::InternalLinkage;
1863 return llvm::GlobalValue::PrivateLinkage;
1867static llvm::GlobalVariable *
1870 std::string SectionName;
1871 if (CGM.
getTriple().isOSBinFormatMachO())
1872 SectionName =
"__DATA, __objc_const";
1873 auto *GV = Builder.finishAndCreateGlobal(
1876 GV->setSection(SectionName);
1892 return EmitClassRef(CGF, ID);
1897 return EmitSelector(CGF, Sel);
1900 return EmitSelectorAddr(Sel);
1907llvm::Constant *CGObjCMac::GetEHType(
QualType T) {
1921 llvm_unreachable(
"asking for catch type for ObjC type in fragile runtime");
1944CGObjCCommonMac::GenerateConstantString(
const StringLiteral *SL) {
1947 : GenerateConstantNSString(SL));
1950static llvm::StringMapEntry<llvm::GlobalVariable *> &
1953 StringRef String = Literal->getString();
1954 StringLength = String.size();
1955 return *Map.insert(std::make_pair(String,
nullptr)).first;
1958llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
1959 if (llvm::Value *
V = ConstantStringClassRef)
1960 return cast<llvm::Constant>(
V);
1964 StringClass.empty() ?
"_NSConstantStringClassReference"
1965 :
"_" + StringClass +
"ClassReference";
1967 llvm::Type *PTy = llvm::ArrayType::get(CGM.
IntTy, 0);
1969 ConstantStringClassRef = GV;
1973llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
1974 if (llvm::Value *
V = ConstantStringClassRef)
1975 return cast<llvm::Constant>(
V);
1979 StringClass.empty() ?
"OBJC_CLASS_$_NSConstantString"
1980 :
"OBJC_CLASS_$_" + StringClass;
1982 ConstantStringClassRef = GV;
1987CGObjCCommonMac::GenerateConstantNSString(
const StringLiteral *Literal) {
1988 unsigned StringLength = 0;
1989 llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
1992 if (
auto *
C = Entry.second)
1997 llvm::Constant *
Class = getNSConstantStringClassRef();
2000 if (!NSConstantStringType) {
2001 NSConstantStringType =
2003 "struct.__builtin_NSString");
2007 auto Fields = Builder.beginStruct(NSConstantStringType);
2014 llvm::ConstantDataArray::getString(VMContext, Entry.first());
2016 llvm::GlobalValue::LinkageTypes
Linkage = llvm::GlobalValue::PrivateLinkage;
2017 bool isConstant = !CGM.
getLangOpts().WritableStrings;
2019 auto *GV =
new llvm::GlobalVariable(CGM.
getModule(),
C->getType(), isConstant,
2021 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2024 GV->setAlignment(llvm::Align(1));
2028 Fields.addInt(CGM.
IntTy, StringLength);
2032 GV = Fields.finishAndCreateGlobal(
"_unnamed_nsstring_", Alignment,
2034 llvm::GlobalVariable::PrivateLinkage);
2035 const char *NSStringSection =
"__OBJC,__cstring_object,regular,no_dead_strip";
2036 const char *NSStringNonFragileABISection =
2037 "__DATA,__objc_stringobj,regular,no_dead_strip";
2040 ? NSStringNonFragileABISection
2060 bool isCategoryImpl,
2061 llvm::Value *Receiver,
2062 bool IsClassMessage,
2070 llvm::Value *ReceiverAsObject =
2071 CGF.
Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
2076 llvm::Type *ClassTyPtr = llvm::PointerType::getUnqual(ObjCTypes.ClassTy);
2078 if (IsClassMessage) {
2079 if (isCategoryImpl) {
2086 Target = EmitClassRef(CGF,
Class->getSuperClass());
2091 llvm::Constant *MetaClassPtr = EmitMetaClassRef(
Class);
2092 llvm::Value *SuperPtr =
2098 }
else if (isCategoryImpl)
2099 Target = EmitClassRef(CGF,
Class->getSuperClass());
2101 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
2108 llvm::Type *ClassTy =
2112 return EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper.
getPointer(),
2113 ObjCTypes.SuperPtrCTy,
true, CallArgs, Method, Class,
2122 llvm::Value *Receiver,
2126 return EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
2128 Method, Class, ObjCTypes);
2142 const ObjCCommonTypesHelper &ObjCTypes) {
2145 llvm::Value *SelValue = llvm::UndefValue::get(Types.ConvertType(selTy));
2149 Arg0 = CGF.
Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
2156 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
2161 "Result type mismatch!");
2163 bool ReceiverCanBeNull =
2164 canMessageReceiverBeNull(CGF, Method, IsSuper, ClassReceiver, Arg0);
2166 bool RequiresNullCheck =
false;
2167 bool RequiresSelValue =
true;
2169 llvm::FunctionCallee Fn =
nullptr;
2175 RequiresSelValue =
false;
2177 if (ReceiverCanBeNull) RequiresNullCheck =
true;
2178 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
2179 : ObjCTypes.getSendStretFn(IsSuper);
2181 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
2182 : ObjCTypes.getSendFpretFn(IsSuper);
2184 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
2185 : ObjCTypes.getSendFp2retFn(IsSuper);
2190 RequiresNullCheck =
true;
2191 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
2192 : ObjCTypes.getSendFn(IsSuper);
2196 llvm::Constant *BitcastFn = cast<llvm::Constant>(
2197 CGF.
Builder.CreateBitCast(Fn.getCallee(), MSI.MessengerType));
2202 RequiresNullCheck =
false;
2206 RequiresNullCheck =
true;
2208 NullReturnState nullReturn;
2209 if (RequiresNullCheck) {
2210 nullReturn.init(CGF, Arg0);
2214 if (RequiresSelValue) {
2215 SelValue = GetSelector(CGF, Sel);
2219 llvm::CallBase *CallSite;
2221 RValue rvalue = CGF.
EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
2226 if (Method && Method->
hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
2227 CallSite->setDoesNotReturn();
2230 return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs,
2231 RequiresNullCheck ? Method :
nullptr);
2235 bool pointee =
false) {
2248 switch (ownership) {
2255 llvm_unreachable(
"bad objc ownership");
2263 if (Ctx.
getLangOpts().getGC() != LangOptions::NonGC) {
2275 IvarInfo(
CharUnits offset, uint64_t sizeInWords)
2276 : Offset(offset), SizeInWords(sizeInWords) {}
2279 bool operator<(
const IvarInfo &other)
const {
2280 return Offset < other.Offset;
2285 class IvarLayoutBuilder {
2296 bool ForStrongLayout;
2299 bool IsDisordered =
false;
2305 CharUnits instanceEnd,
bool forStrongLayout)
2306 : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
2307 ForStrongLayout(forStrongLayout) {
2312 template <
class Iterator,
class GetOffsetFn>
2313 void visitAggregate(Iterator begin, Iterator end,
2315 const GetOffsetFn &getOffset);
2323 bool hasBitmapData()
const {
return !IvarsInfo.empty(); }
2325 llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
2329 const unsigned char *
s = buffer.data();
2330 for (
unsigned i = 0, e = buffer.size(); i < e; i++)
2332 printf(
"0x0%x%s",
s[i],
s[i] != 0 ?
", " :
"");
2334 printf(
"0x%x%s",
s[i],
s[i] != 0 ?
", " :
"");
2340llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(
CodeGenModule &CGM,
2343 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2344 if (CGM.
getLangOpts().getGC() == LangOptions::NonGC)
2350 builder.visitBlock(blockInfo);
2352 if (!builder.hasBitmapData())
2356 llvm::Constant *
C = builder.buildBitmap(*
this, buffer);
2357 if (CGM.
getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
2358 printf(
"\n block variable layout for block: ");
2359 builder.dump(buffer);
2365void IvarLayoutBuilder::visitBlock(
const CGBlockInfo &blockInfo) {
2378 for (
const auto &CI :
blockDecl->captures()) {
2379 const VarDecl *variable = CI.getVariable();
2391 if (fieldOffset < lastFieldOffset)
2392 IsDisordered =
true;
2393 lastFieldOffset = fieldOffset;
2397 IvarsInfo.push_back(IvarInfo(fieldOffset, 1));
2401 assert(!
type->isArrayType() &&
"array variable should not be caught");
2403 visitRecord(record, fieldOffset);
2412 IvarsInfo.push_back(IvarInfo(fieldOffset, 1));
2437void CGObjCCommonMac::UpdateRunSkipBlockVars(
bool IsByref,
2443 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
2446 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
2449 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
2452 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
2455 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2460void CGObjCCommonMac::BuildRCRecordLayout(
const llvm::StructLayout *RecLayout,
2465 bool IsUnion = (RD && RD->
isUnion());
2468 const FieldDecl *LastFieldBitfieldOrUnnamed =
nullptr;
2472 if (RecFields.empty())
2476 for (
unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2485 if (!
Field->getIdentifier() ||
Field->isBitField()) {
2486 LastFieldBitfieldOrUnnamed =
Field;
2487 LastBitfieldOrUnnamedOffset = FieldOffset;
2491 LastFieldBitfieldOrUnnamed =
nullptr;
2498 BytePos + FieldOffset, HasUnion);
2503 auto *CArray = cast<ConstantArrayType>(Array);
2504 uint64_t ElCount = CArray->getSize().getZExtValue();
2505 assert(CArray &&
"only array with known element size is supported");
2506 FQT = CArray->getElementType();
2508 auto *CArray = cast<ConstantArrayType>(Array);
2509 ElCount *= CArray->getSize().getZExtValue();
2510 FQT = CArray->getElementType();
2513 int OldIndex = RunSkipBlockVars.size() - 1;
2515 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset, HasUnion);
2520 for (
int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
2522 for (
int i = OldIndex+1; i <= FirstIndex; ++i)
2523 RunSkipBlockVars.push_back(
2524 RUN_SKIP(RunSkipBlockVars[i].opcode,
2525 RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
2526 RunSkipBlockVars[i].block_var_size));
2534 if (UnionIvarSize > MaxUnionSize) {
2535 MaxUnionSize = UnionIvarSize;
2537 MaxFieldOffset = FieldOffset;
2540 UpdateRunSkipBlockVars(
false,
2541 getBlockCaptureLifetime(FQT, ByrefLayout),
2542 BytePos + FieldOffset,
2547 if (LastFieldBitfieldOrUnnamed) {
2548 if (LastFieldBitfieldOrUnnamed->
isBitField()) {
2552 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
2553 ((BitFieldSize % ByteSizeInBits) != 0);
2555 Size += LastBitfieldOrUnnamedOffset;
2556 UpdateRunSkipBlockVars(
false,
2557 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->
getType(),
2559 BytePos + LastBitfieldOrUnnamedOffset,
2562 assert(!LastFieldBitfieldOrUnnamed->
getIdentifier() &&
"Expected unnamed");
2566 UpdateRunSkipBlockVars(
false,
2567 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->
getType(),
2569 BytePos + LastBitfieldOrUnnamedOffset,
2575 UpdateRunSkipBlockVars(
false,
2576 getBlockCaptureLifetime(MaxField->
getType(), ByrefLayout),
2577 BytePos + MaxFieldOffset,
2581void CGObjCCommonMac::BuildRCBlockVarRecordLayout(
const RecordType *RT,
2588 const llvm::StructLayout *RecLayout =
2589 CGM.
getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
2591 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
2603uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2606 if (Layout.size() <= 3) {
2607 unsigned size = Layout.size();
2608 unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
2610 enum BLOCK_LAYOUT_OPCODE opcode ;
2614 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2615 if (opcode == BLOCK_LAYOUT_STRONG)
2616 strong_word_count = (inst & 0xF)+1;
2620 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2621 if (opcode == BLOCK_LAYOUT_BYREF)
2622 byref_word_count = (inst & 0xF)+1;
2626 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2627 if (opcode == BLOCK_LAYOUT_WEAK)
2628 weak_word_count = (inst & 0xF)+1;
2635 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2636 if (opcode == BLOCK_LAYOUT_STRONG) {
2637 strong_word_count = (inst & 0xF)+1;
2639 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2640 if (opcode == BLOCK_LAYOUT_BYREF)
2641 byref_word_count = (inst & 0xF)+1;
2642 else if (opcode == BLOCK_LAYOUT_WEAK)
2643 weak_word_count = (inst & 0xF)+1;
2647 else if (opcode == BLOCK_LAYOUT_BYREF) {
2648 byref_word_count = (inst & 0xF)+1;
2650 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2651 if (opcode == BLOCK_LAYOUT_WEAK)
2652 weak_word_count = (inst & 0xF)+1;
2662 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2663 if (opcode == BLOCK_LAYOUT_STRONG)
2664 strong_word_count = (inst & 0xF)+1;
2665 else if (opcode == BLOCK_LAYOUT_BYREF)
2666 byref_word_count = (inst & 0xF)+1;
2667 else if (opcode == BLOCK_LAYOUT_WEAK)
2668 weak_word_count = (inst & 0xF)+1;
2680 if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
2684 (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
2686 if (size == count) {
2687 if (strong_word_count)
2688 Result = strong_word_count;
2690 if (byref_word_count)
2691 Result += byref_word_count;
2693 if (weak_word_count)
2694 Result += weak_word_count;
2700llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(
bool ComputeByrefLayout) {
2701 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2702 if (RunSkipBlockVars.empty())
2706 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2710 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2713 unsigned size = RunSkipBlockVars.size();
2714 for (
unsigned i = 0; i < size; i++) {
2715 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2716 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2717 CharUnits end_byte_pos = start_byte_pos;
2720 if (opcode == RunSkipBlockVars[j].opcode) {
2721 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2728 end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2731 RunSkipBlockVars[j].block_var_bytepos -
2732 RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
2733 size_in_bytes += gap;
2736 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2737 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2738 size_in_bytes -= residue_in_bytes;
2739 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2742 unsigned size_in_words = size_in_bytes.
getQuantity() / WordSizeInBytes;
2743 while (size_in_words >= 16) {
2746 unsigned char inst = (opcode << 4) | 0xf;
2747 Layout.push_back(inst);
2748 size_in_words -= 16;
2750 if (size_in_words > 0) {
2753 unsigned char inst = (opcode << 4) | (size_in_words-1);
2754 Layout.push_back(inst);
2757 unsigned char inst =
2758 (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.
getQuantity()-1);
2759 Layout.push_back(inst);
2763 while (!Layout.empty()) {
2764 unsigned char inst = Layout.back();
2765 enum BLOCK_LAYOUT_OPCODE opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2766 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2772 uint64_t Result = InlineLayoutInstruction(Layout);
2776 if (ComputeByrefLayout)
2777 printf(
"\n Inline BYREF variable layout: ");
2779 printf(
"\n Inline block variable layout: ");
2780 printf(
"0x0%" PRIx64
"", Result);
2781 if (
auto numStrong = (Result & 0xF00) >> 8)
2782 printf(
", BL_STRONG:%d", (
int) numStrong);
2783 if (
auto numByref = (Result & 0x0F0) >> 4)
2784 printf(
", BL_BYREF:%d", (
int) numByref);
2785 if (
auto numWeak = (Result & 0x00F) >> 0)
2786 printf(
", BL_WEAK:%d", (
int) numWeak);
2787 printf(
", BL_OPERATOR:0\n");
2789 return llvm::ConstantInt::get(CGM.
IntPtrTy, Result);
2792 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2793 Layout.push_back(inst);
2795 for (
unsigned i = 0, e = Layout.size(); i != e; i++)
2796 BitMap += Layout[i];
2799 if (ComputeByrefLayout)
2800 printf(
"\n Byref variable layout: ");
2802 printf(
"\n Block variable layout: ");
2803 for (
unsigned i = 0, e = BitMap.size(); i != e; i++) {
2804 unsigned char inst = BitMap[i];
2805 enum BLOCK_LAYOUT_OPCODE opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2808 case BLOCK_LAYOUT_OPERATOR:
2812 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2813 printf(
"BL_NON_OBJECT_BYTES:");
2815 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2816 printf(
"BL_NON_OBJECT_WORD:");
2818 case BLOCK_LAYOUT_STRONG:
2821 case BLOCK_LAYOUT_BYREF:
2824 case BLOCK_LAYOUT_WEAK:
2827 case BLOCK_LAYOUT_UNRETAINED:
2828 printf(
"BL_UNRETAINED:");
2833 printf(
"%d", (inst & 0xf) + delta);
2841 auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
2849 bool HasCopyDisposeHelpers) {
2851 for (
const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) {
2852 if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) {
2856 }
else if (HasCopyDisposeHelpers) {
2864 case CGObjCCommonMac::BLOCK_LAYOUT_STRONG:
2867 case CGObjCCommonMac::BLOCK_LAYOUT_BYREF:
2870 case CGObjCCommonMac::BLOCK_LAYOUT_WEAK:
2877 Str += llvm::to_string(R.block_var_bytepos.getQuantity());
2878 Str +=
"l" + llvm::to_string(R.block_var_size.getQuantity());
2883void CGObjCCommonMac::fillRunSkipBlockVars(
CodeGenModule &CGM,
2885 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
2887 RunSkipBlockVars.clear();
2888 bool hasUnion =
false;
2892 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2897 const llvm::StructLayout *layout =
2907 for (
const auto &CI :
blockDecl->captures()) {
2908 const VarDecl *variable = CI.getVariable();
2919 assert(!
type->isArrayType() &&
"array variable should not be caught");
2922 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2930 UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(
type,
false),
2931 fieldOffset, fieldSize);
2938 fillRunSkipBlockVars(CGM, blockInfo);
2939 return getBitmapBlockLayout(
false);
2942std::string CGObjCCommonMac::getRCBlockLayoutStr(
CodeGenModule &CGM,
2944 fillRunSkipBlockVars(CGM, blockInfo);
2950 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
2951 assert(!T->
isArrayType() &&
"__block array variable should not be caught");
2953 RunSkipBlockVars.clear();
2954 bool hasUnion =
false;
2956 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion,
true );
2957 llvm::Constant *Result = getBitmapBlockLayout(
true);
2958 if (isa<llvm::ConstantInt>(Result))
2959 Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.
Int8PtrTy);
2962 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2972 return GetProtocolRef(PD);
2984 GetOrEmitProtocol(PD);
2987llvm::Constant *CGObjCCommonMac::GetProtocolRef(
const ObjCProtocolDecl *PD) {
2989 return GetOrEmitProtocol(PD);
2991 return GetOrEmitProtocolRef(PD);
2994llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime(
2997 ObjCCommonTypesHelper &ObjCTypes) {
2998 llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn();
3000 llvm::Value *className = CGF.
CGM
3002 ID->getObjCRuntimeNameAsString()))
3006 CGF.
Builder.CreateBitCast(className,
3009 llvm::CallInst *call = CGF.
Builder.CreateCall(lookUpClassFn, className);
3010 call->setDoesNotThrow();
3027 llvm::GlobalVariable *Entry = Protocols[PD->
getIdentifier()];
3030 if (Entry && Entry->hasInitializer())
3042 auto methodLists = ProtocolMethodLists::get(PD);
3045 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
3046 values.add(EmitProtocolExtension(PD, methodLists));
3048 values.add(EmitProtocolList(
"OBJC_PROTOCOL_REFS_" + PD->
getName(),
3050 values.add(methodLists.emitMethodList(
this, PD,
3051 ProtocolMethodLists::RequiredInstanceMethods));
3052 values.add(methodLists.emitMethodList(
this, PD,
3053 ProtocolMethodLists::RequiredClassMethods));
3057 assert(Entry->hasPrivateLinkage());
3058 values.finishAndSetAsInitializer(Entry);
3060 Entry = values.finishAndCreateGlobal(
"OBJC_PROTOCOL_" + PD->
getName(),
3063 llvm::GlobalValue::PrivateLinkage);
3064 Entry->setSection(
"__OBJC,__protocol,regular,no_dead_strip");
3073llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD) {
3074 llvm::GlobalVariable *&Entry = Protocols[PD->
getIdentifier()];
3080 Entry =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ProtocolTy,
3081 false, llvm::GlobalValue::PrivateLinkage,
3082 nullptr,
"OBJC_PROTOCOL_" + PD->
getName());
3083 Entry->setSection(
"__OBJC,__protocol,regular,no_dead_strip");
3085 Entry->setAlignment(llvm::Align(4));
3103 const ProtocolMethodLists &methodLists) {
3104 auto optInstanceMethods =
3105 methodLists.emitMethodList(
this, PD,
3106 ProtocolMethodLists::OptionalInstanceMethods);
3107 auto optClassMethods =
3108 methodLists.emitMethodList(
this, PD,
3109 ProtocolMethodLists::OptionalClassMethods);
3111 auto extendedMethodTypes =
3112 EmitProtocolMethodTypes(
"OBJC_PROTOCOL_METHOD_TYPES_" + PD->
getName(),
3113 methodLists.emitExtendedTypesArray(
this),
3116 auto instanceProperties =
3117 EmitPropertyList(
"OBJC_$_PROP_PROTO_LIST_" + PD->
getName(),
nullptr, PD,
3119 auto classProperties =
3120 EmitPropertyList(
"OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->
getName(),
nullptr,
3121 PD, ObjCTypes,
true);
3124 if (optInstanceMethods->isNullValue() &&
3125 optClassMethods->isNullValue() &&
3126 extendedMethodTypes->isNullValue() &&
3127 instanceProperties->isNullValue() &&
3128 classProperties->isNullValue()) {
3129 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
3133 CGM.
getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
3136 auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
3137 values.addInt(ObjCTypes.IntTy, size);
3138 values.add(optInstanceMethods);
3139 values.add(optClassMethods);
3140 values.add(instanceProperties);
3141 values.add(extendedMethodTypes);
3142 values.add(classProperties);
3145 return CreateMetadataVar(
"_OBJC_PROTOCOLEXT_" + PD->
getName(), values,
3157CGObjCMac::EmitProtocolList(Twine name,
3161 auto PDs = GetRuntimeProtocolList(begin, end);
3163 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
3166 auto values = builder.beginStruct();
3169 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
3172 auto countSlot = values.addPlaceholder();
3174 auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
3175 for (
const auto *Proto : PDs)
3176 refsArray.add(GetProtocolRef(Proto));
3178 auto count = refsArray.size();
3181 refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
3183 refsArray.finishAndAddTo(values);
3184 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
3187 if (CGM.
getTriple().isOSBinFormatMachO())
3188 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3190 llvm::GlobalVariable *GV =
3191 CreateMetadataVar(name, values, section, CGM.
getPointerAlign(),
false);
3199 bool IsClassProperty) {
3201 if (IsClassProperty != PD->isClassProperty())
3205 Properties.push_back(PD);
3224llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
3225 const Decl *Container,
3227 const ObjCCommonTypesHelper &ObjCTypes,
3228 bool IsClassProperty) {
3229 if (IsClassProperty) {
3233 if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
3234 (Triple.isiOS() && Triple.isOSVersionLT(9)))
3235 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3243 for (
auto *PD : ClassExt->properties()) {
3244 if (IsClassProperty != PD->isClassProperty())
3246 if (PD->isDirectProperty())
3249 Properties.push_back(PD);
3253 if (IsClassProperty != PD->isClassProperty())
3259 if (PD->isDirectProperty())
3261 Properties.push_back(PD);
3265 for (
const auto *
P : OID->all_referenced_protocols())
3269 for (
const auto *
P : CD->protocols())
3274 if (Properties.empty())
3275 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3277 unsigned propertySize =
3281 auto values = builder.beginStruct();
3282 values.addInt(ObjCTypes.IntTy, propertySize);
3283 values.addInt(ObjCTypes.IntTy, Properties.size());
3284 auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
3285 for (
auto PD : Properties) {
3286 auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
3288 property.add(GetPropertyTypeString(PD, Container));
3289 property.finishAndAddTo(propertiesArray);
3291 propertiesArray.finishAndAddTo(values);
3294 if (CGM.
getTriple().isOSBinFormatMachO())
3295 Section = (ObjCABI == 2) ?
"__DATA, __objc_const"
3296 :
"__OBJC,__property,regular,no_dead_strip";
3298 llvm::GlobalVariable *GV =
3299 CreateMetadataVar(Name, values, Section, CGM.
getPointerAlign(),
true);
3304CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
3306 const ObjCCommonTypesHelper &ObjCTypes) {
3308 if (MethodTypes.empty())
3309 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
3311 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3312 MethodTypes.size());
3313 llvm::Constant *
Init = llvm::ConstantArray::get(AT, MethodTypes);
3316 if (CGM.
getTriple().isOSBinFormatMachO() && ObjCABI == 2)
3317 Section =
"__DATA, __objc_const";
3319 llvm::GlobalVariable *GV =
3348 llvm::raw_svector_ostream(ExtName) <<
Interface->getName() <<
'_'
3352 auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
3360 for (
const auto *MD : OCD->
methods()) {
3361 if (!MD->isDirectMethod())
3362 Methods[
unsigned(MD->isClassMethod())].push_back(MD);
3365 Values.add(GetClassName(OCD->
getName()));
3366 Values.add(GetClassName(
Interface->getObjCRuntimeNameAsString()));
3367 LazySymbols.insert(
Interface->getIdentifier());
3369 Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
3370 Methods[InstanceMethods]));
3371 Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
3372 Methods[ClassMethods]));
3375 EmitProtocolList(
"OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
3378 Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
3380 Values.addInt(ObjCTypes.IntTy, Size);
3384 Values.add(EmitPropertyList(
"_OBJC_$_PROP_LIST_" + ExtName.str(),
3386 Values.add(EmitPropertyList(
"_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
3389 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3390 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3393 llvm::GlobalVariable *GV =
3394 CreateMetadataVar(
"OBJC_CATEGORY_" + ExtName.str(), Values,
3395 "__OBJC,__category,regular,no_dead_strip",
3397 DefinedCategories.push_back(GV);
3398 DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
3400 MethodDefinitions.clear();
3460 for (
auto *field : recType->getDecl()->fields()) {
3475 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
3478 ID->getClassInterface()->all_declared_ivar_begin();
3479 ivar; ivar = ivar->getNextIvar()) {
3509 DefinedSymbols.insert(RuntimeName);
3511 std::string ClassName =
ID->getNameAsString();
3515 llvm::Constant *Protocols =
3516 EmitProtocolList(
"OBJC_CLASS_PROTOCOLS_" +
ID->getName(),
3517 Interface->all_referenced_protocol_begin(),
3518 Interface->all_referenced_protocol_end());
3520 if (
ID->hasNonZeroConstructors() ||
ID->hasDestructors())
3523 bool hasMRCWeak =
false;
3543 for (
const auto *MD :
ID->methods()) {
3544 if (!MD->isDirectMethod())
3545 Methods[
unsigned(MD->isClassMethod())].push_back(MD);
3548 for (
const auto *PID :
ID->property_impls()) {
3550 if (PID->getPropertyDecl()->isDirectProperty())
3553 if (GetMethodDefinition(MD))
3554 Methods[InstanceMethods].push_back(MD);
3556 if (GetMethodDefinition(MD))
3557 Methods[InstanceMethods].push_back(MD);
3562 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3563 values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
3566 LazySymbols.insert(Super->getIdentifier());
3568 values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
3570 values.addNullPointer(ObjCTypes.ClassPtrTy);
3572 values.add(GetClassName(
ID->getObjCRuntimeNameAsString()));
3574 values.addInt(ObjCTypes.LongTy, 0);
3575 values.addInt(ObjCTypes.LongTy, Flags);
3576 values.addInt(ObjCTypes.LongTy,
Size.getQuantity());
3577 values.add(EmitIvarList(ID,
false));
3578 values.add(emitMethodList(
ID->getName(), MethodListType::InstanceMethods,
3579 Methods[InstanceMethods]));
3581 values.addNullPointer(ObjCTypes.CachePtrTy);
3582 values.add(Protocols);
3584 values.add(EmitClassExtension(ID, Size, hasMRCWeak,
3587 std::string Name(
"OBJC_CLASS_");
3589 const char *Section =
"__OBJC,__class,regular,no_dead_strip";
3591 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3593 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3594 "Forward metaclass reference has incorrect type.");
3595 values.finishAndSetAsInitializer(GV);
3596 GV->setSection(Section);
3600 GV = CreateMetadataVar(Name, values, Section, CGM.
getPointerAlign(),
true);
3601 DefinedClasses.push_back(GV);
3602 ImplementedClasses.push_back(
Interface);
3604 MethodDefinitions.clear();
3608 llvm::Constant *Protocols,
3617 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3627 values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
3629 values.addNullPointer(ObjCTypes.ClassPtrTy);
3631 values.add(GetClassName(
ID->getObjCRuntimeNameAsString()));
3633 values.addInt(ObjCTypes.LongTy, 0);
3634 values.addInt(ObjCTypes.LongTy, Flags);
3635 values.addInt(ObjCTypes.LongTy, Size);
3636 values.add(EmitIvarList(ID,
true));
3637 values.add(emitMethodList(
ID->getName(), MethodListType::ClassMethods,
3640 values.addNullPointer(ObjCTypes.CachePtrTy);
3641 values.add(Protocols);
3643 values.addNullPointer(ObjCTypes.Int8PtrTy);
3648 std::string Name(
"OBJC_METACLASS_");
3649 Name +=
ID->getName();
3652 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3654 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3655 "Forward metaclass reference has incorrect type.");
3656 values.finishAndSetAsInitializer(GV);
3660 llvm::GlobalValue::PrivateLinkage);
3662 GV->setSection(
"__OBJC,__meta_class,regular,no_dead_strip");
3669 std::string Name =
"OBJC_METACLASS_" +
ID->getNameAsString();
3679 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3681 GV =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ClassTy,
false,
3682 llvm::GlobalValue::PrivateLinkage,
nullptr,
3685 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3686 "Forward metaclass reference has incorrect type.");
3691 std::string Name =
"OBJC_CLASS_" +
ID->getNameAsString();
3692 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3695 GV =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ClassTy,
false,
3696 llvm::GlobalValue::PrivateLinkage,
nullptr,
3699 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3700 "Forward class metadata reference has incorrect type.");
3720 llvm::Constant *layout;
3722 layout = llvm::ConstantPointerNull::get(CGM.
Int8PtrTy);
3729 llvm::Constant *propertyList =
3730 EmitPropertyList((isMetaclass ? Twine(
"_OBJC_$_CLASS_PROP_LIST_")
3731 : Twine(
"_OBJC_$_PROP_LIST_"))
3733 ID,
ID->getClassInterface(), ObjCTypes, isMetaclass);
3736 if (layout->isNullValue() && propertyList->isNullValue()) {
3737 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
3741 CGM.
getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
3744 auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
3745 values.addInt(ObjCTypes.IntTy, size);
3747 values.add(propertyList);
3749 return CreateMetadataVar(
"OBJC_CLASSEXT_" +
ID->getName(), values,
3750 "__OBJC,__class_ext,regular,no_dead_strip",
3774 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
3779 auto ivarList = builder.beginStruct();
3780 auto countSlot = ivarList.addPlaceholder();
3781 auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
3786 if (!IVD->getDeclName())
3789 auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
3790 ivar.add(GetMethodVarName(IVD->getIdentifier()));
3791 ivar.add(GetMethodVarType(IVD));
3792 ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
3793 ivar.finishAndAddTo(ivars);
3797 auto count = ivars.size();
3801 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
3804 ivars.finishAndAddTo(ivarList);
3805 ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
3807 llvm::GlobalVariable *GV;
3808 GV = CreateMetadataVar(
"OBJC_INSTANCE_VARIABLES_" +
ID->getName(), ivarList,
3809 "__OBJC,__instance_vars,regular,no_dead_strip",
3822 auto description = builder.
beginStruct(ObjCTypes.MethodDescriptionTy);
3823 description.add(GetMethodVarName(MD->
getSelector()));
3824 description.add(GetMethodVarType(MD));
3825 description.finishAndAddTo(builder);
3837 llvm::Function *fn = GetMethodDefinition(MD);
3838 assert(fn &&
"no definition registered for method");
3840 auto method = builder.
beginStruct(ObjCTypes.MethodTy);
3842 method.add(GetMethodVarType(MD));
3844 method.finishAndAddTo(builder);
3860llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
3864 bool forProtocol =
false;
3866 case MethodListType::CategoryInstanceMethods:
3867 prefix =
"OBJC_CATEGORY_INSTANCE_METHODS_";
3868 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3869 forProtocol =
false;
3871 case MethodListType::CategoryClassMethods:
3872 prefix =
"OBJC_CATEGORY_CLASS_METHODS_";
3873 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3874 forProtocol =
false;
3876 case MethodListType::InstanceMethods:
3877 prefix =
"OBJC_INSTANCE_METHODS_";
3878 section =
"__OBJC,__inst_meth,regular,no_dead_strip";
3879 forProtocol =
false;
3881 case MethodListType::ClassMethods:
3882 prefix =
"OBJC_CLASS_METHODS_";
3883 section =
"__OBJC,__cls_meth,regular,no_dead_strip";
3884 forProtocol =
false;
3886 case MethodListType::ProtocolInstanceMethods:
3887 prefix =
"OBJC_PROTOCOL_INSTANCE_METHODS_";
3888 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3891 case MethodListType::ProtocolClassMethods:
3892 prefix =
"OBJC_PROTOCOL_CLASS_METHODS_";
3893 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3896 case MethodListType::OptionalProtocolInstanceMethods:
3897 prefix =
"OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
3898 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3901 case MethodListType::OptionalProtocolClassMethods:
3902 prefix =
"OBJC_PROTOCOL_CLASS_METHODS_OPT_";
3903 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3909 if (methods.empty())
3910 return llvm::Constant::getNullValue(forProtocol
3911 ? ObjCTypes.MethodDescriptionListPtrTy
3912 : ObjCTypes.MethodListPtrTy);
3919 values.addInt(ObjCTypes.IntTy, methods.size());
3920 auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
3921 for (
auto MD : methods) {
3922 emitMethodDescriptionConstant(methodArray, MD);
3924 methodArray.finishAndAddTo(values);
3926 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3934 values.addNullPointer(ObjCTypes.Int8PtrTy);
3935 values.addInt(ObjCTypes.IntTy, methods.size());
3936 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
3937 for (
auto MD : methods) {
3939 emitMethodConstant(methodArray, MD);
3941 methodArray.finishAndAddTo(values);
3943 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3948llvm::Function *CGObjCCommonMac::GenerateMethod(
const ObjCMethodDecl *OMD,
3950 llvm::Function *Method;
3953 Method = GenerateDirectMethod(OMD, CD);
3955 auto Name = getSymbolNameForMethod(OMD);
3958 llvm::FunctionType *MethodTy =
3959 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
3961 llvm::Function::Create(MethodTy, llvm::GlobalValue::InternalLinkage,
3965 MethodDefinitions.insert(std::make_pair(OMD, Method));
3974 auto I = DirectMethodDefinitions.find(COMD);
3975 llvm::Function *OldFn =
nullptr, *Fn =
nullptr;
3977 if (I != DirectMethodDefinitions.end()) {
3993 llvm::FunctionType *MethodTy =
3994 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
3997 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
3999 Fn->takeName(OldFn);
4000 OldFn->replaceAllUsesWith(Fn);
4001 OldFn->eraseFromParent();
4006 auto Name = getSymbolNameForMethod(OMD,
false);
4008 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
4010 DirectMethodDefinitions.insert(std::make_pair(COMD, Fn));
4016void CGObjCCommonMac::GenerateDirectMethodPrologue(
4020 bool ReceiverCanBeNull =
true;
4022 auto selfValue = Builder.CreateLoad(selfAddr);
4040 "GenerateDirectMethod() should be called with the Class Interface");
4053 result = GeneratePossiblySpecializedMessageSend(
4061 ReceiverCanBeNull = isWeakLinkedClass(OID);
4064 if (ReceiverCanBeNull) {
4065 llvm::BasicBlock *SelfIsNilBlock =
4067 llvm::BasicBlock *ContBlock =
4071 auto selfTy = cast<llvm::PointerType>(selfValue->getType());
4072 auto Zero = llvm::ConstantPointerNull::get(selfTy);
4075 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero), SelfIsNilBlock,
4076 ContBlock, MDHelper.createBranchWeights(1, 1 << 20));
4082 Builder.SetInsertPoint(SelfIsNilBlock);
4083 if (!retTy->isVoidType()) {
4091 Builder.SetInsertPoint(ContBlock);
4099 Builder.CreateStore(GetSelector(CGF, OMD),
4104llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
4109 llvm::GlobalValue::LinkageTypes
LT =
4111 llvm::GlobalVariable *GV =
4112 Init.finishAndCreateGlobal(Name, Align,
false,
LT);
4113 if (!Section.empty())
4114 GV->setSection(Section);
4120llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
4121 llvm::Constant *
Init,
4125 llvm::Type *Ty =
Init->getType();
4126 llvm::GlobalValue::LinkageTypes
LT =
4128 llvm::GlobalVariable *GV =
4130 if (!Section.empty())
4131 GV->setSection(Section);
4138llvm::GlobalVariable *
4139CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType
Type,
4140 bool ForceNonFragileABI,
4141 bool NullTerminate) {
4144 case ObjCLabelType::ClassName:
Label =
"OBJC_CLASS_NAME_";
break;
4145 case ObjCLabelType::MethodVarName:
Label =
"OBJC_METH_VAR_NAME_";
break;
4146 case ObjCLabelType::MethodVarType:
Label =
"OBJC_METH_VAR_TYPE_";
break;
4147 case ObjCLabelType::PropertyName:
Label =
"OBJC_PROP_NAME_ATTR_";
break;
4150 bool NonFragile = ForceNonFragileABI || isNonFragileABI();
4154 case ObjCLabelType::ClassName:
4155 Section = NonFragile ?
"__TEXT,__objc_classname,cstring_literals"
4156 :
"__TEXT,__cstring,cstring_literals";
4158 case ObjCLabelType::MethodVarName:
4159 Section = NonFragile ?
"__TEXT,__objc_methname,cstring_literals"
4160 :
"__TEXT,__cstring,cstring_literals";
4162 case ObjCLabelType::MethodVarType:
4163 Section = NonFragile ?
"__TEXT,__objc_methtype,cstring_literals"
4164 :
"__TEXT,__cstring,cstring_literals";
4166 case ObjCLabelType::PropertyName:
4167 Section = NonFragile ?
"__TEXT,__objc_methname,cstring_literals"
4168 :
"__TEXT,__cstring,cstring_literals";
4172 llvm::Constant *
Value =
4173 llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
4174 llvm::GlobalVariable *GV =
4177 llvm::GlobalValue::PrivateLinkage,
Value,
Label);
4178 if (CGM.
getTriple().isOSBinFormatMachO())
4179 GV->setSection(Section);
4180 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4187llvm::Function *CGObjCMac::ModuleInitFunction() {
4193llvm::FunctionCallee CGObjCMac::GetPropertyGetFunction() {
4194 return ObjCTypes.getGetPropertyFn();
4197llvm::FunctionCallee CGObjCMac::GetPropertySetFunction() {
4198 return ObjCTypes.getSetPropertyFn();
4201llvm::FunctionCallee CGObjCMac::GetOptimizedPropertySetFunction(
bool atomic,
4203 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
4206llvm::FunctionCallee CGObjCMac::GetGetStructFunction() {
4207 return ObjCTypes.getCopyStructFn();
4210llvm::FunctionCallee CGObjCMac::GetSetStructFunction() {
4211 return ObjCTypes.getCopyStructFn();
4214llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectGetFunction() {
4215 return ObjCTypes.getCppAtomicObjectFunction();
4218llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectSetFunction() {
4219 return ObjCTypes.getCppAtomicObjectFunction();
4222llvm::FunctionCallee CGObjCMac::EnumerationMutationFunction() {
4223 return ObjCTypes.getEnumerationMutationFn();
4227 return EmitTryOrSynchronizedStmt(CGF, S);
4232 return EmitTryOrSynchronizedStmt(CGF, S);
4241 ObjCTypesHelper &ObjCTypes;
4242 PerformFragileFinally(
const Stmt *S,
4246 ObjCTypesHelper *ObjCTypes)
4247 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
4248 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
4253 llvm::BasicBlock *FinallyCallExit =
4255 llvm::BasicBlock *FinallyNoCallExit =
4258 FinallyCallExit, FinallyNoCallExit);
4266 if (isa<ObjCAtTryStmt>(S)) {
4268 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
4270 if (flags.isForEHCleanup())
return;
4274 llvm::Value *CurCleanupDest =
4277 CGF.
EmitStmt(FinallyStmt->getFinallyBody());
4296 class FragileHazards {
4301 llvm::InlineAsm *ReadHazard;
4302 llvm::InlineAsm *WriteHazard;
4304 llvm::FunctionType *GetAsmFnType();
4306 void collectLocals();
4312 void emitWriteHazard();
4313 void emitHazardsInNewBlocks();
4325 if (Locals.empty())
return;
4328 for (llvm::Function::iterator
4329 I = CGF.
CurFn->begin(), E = CGF.
CurFn->end(); I != E; ++I)
4330 BlocksBeforeTry.insert(&*I);
4332 llvm::FunctionType *AsmFnTy = GetAsmFnType();
4340 std::string Constraint;
4341 for (
unsigned I = 0, E = Locals.size(); I != E; ++I) {
4342 if (I) Constraint +=
',';
4346 ReadHazard = llvm::InlineAsm::get(AsmFnTy,
"", Constraint,
true,
false);
4354 std::string Constraint;
4355 for (
unsigned I = 0, E = Locals.size(); I != E; ++I) {
4356 if (I) Constraint +=
',';
4357 Constraint +=
"=*m";
4360 WriteHazard = llvm::InlineAsm::get(AsmFnTy,
"", Constraint,
true,
false);
4365void FragileHazards::emitWriteHazard() {
4366 if (Locals.empty())
return;
4369 for (
auto Pair : llvm::enumerate(Locals))
4370 Call->addParamAttr(Pair.index(), llvm::Attribute::get(
4372 cast<llvm::AllocaInst>(Pair.value())->getAllocatedType()));
4375void FragileHazards::emitReadHazard(
CGBuilderTy &Builder) {
4376 assert(!Locals.empty());
4377 llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
4378 call->setDoesNotThrow();
4380 for (
auto Pair : llvm::enumerate(Locals))
4381 call->addParamAttr(Pair.index(), llvm::Attribute::get(
4382 Builder.getContext(), llvm::Attribute::ElementType,
4383 cast<llvm::AllocaInst>(Pair.value())->getAllocatedType()));
4388void FragileHazards::emitHazardsInNewBlocks() {
4389 if (Locals.empty())
return;
4394 for (llvm::Function::iterator
4395 FI = CGF.
CurFn->begin(), FE = CGF.
CurFn->end(); FI != FE; ++FI) {
4396 llvm::BasicBlock &BB = *FI;
4397 if (BlocksBeforeTry.count(&BB))
continue;
4400 for (llvm::BasicBlock::iterator
4401 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
4402 llvm::Instruction &I = *BI;
4406 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I))
4408 if (isa<llvm::IntrinsicInst>(I))
4413 if (cast<llvm::CallBase>(I).doesNotThrow())
4421 Builder.SetInsertPoint(&BB, BI);
4422 emitReadHazard(Builder);
4428 if (
V.isValid()) S.insert(
V.getPointer());
4431void FragileHazards::collectLocals() {
4439 llvm::BasicBlock &Entry = CGF.
CurFn->getEntryBlock();
4440 for (llvm::BasicBlock::iterator
4441 I = Entry.begin(), E = Entry.end(); I != E; ++I)
4442 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
4443 Locals.push_back(&*I);
4446llvm::FunctionType *FragileHazards::GetAsmFnType() {
4448 for (
unsigned i = 0, e = Locals.size(); i != e; ++i)
4449 tys[i] = Locals[i]->getType();
4450 return llvm::FunctionType::get(CGF.
VoidTy, tys,
false);
4563 bool isTry = isa<ObjCAtTryStmt>(S);
4567 CodeGenFunction::JumpDest FinallyEnd =
4572 CodeGenFunction::JumpDest FinallyRethrow =
4582 llvm::Value *SyncArg =
4583 CGF.
EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
4584 SyncArg = CGF.
Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
4596 "exceptiondata.ptr");
4602 FragileHazards Hazards(CGF);
4631 ExceptionData.getPointer());
4634 llvm::Constant *
Zero = llvm::ConstantInt::get(CGF.
Builder.getInt32Ty(), 0);
4637 ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes,
4640 ObjCTypes.getSetJmpFn(), SetJmpBuffer,
"setjmp_result");
4641 SetJmpResult->setCanReturnTwice();
4647 llvm::Value *DidCatch =
4648 CGF.
Builder.CreateIsNotNull(SetJmpResult,
"did_catch_exception");
4649 CGF.
Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
4654 CGF.
EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
4655 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
4657 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.
Builder.saveAndClearIP();
4663 Hazards.emitWriteHazard();
4667 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
4676 llvm::CallInst *Caught =
4678 ExceptionData.getPointer(),
"caught");
4688 llvm::BasicBlock *CatchBlock =
nullptr;
4689 llvm::BasicBlock *CatchHandler =
nullptr;
4695 "propagating_exception");
4701 ExceptionData.getPointer());
4703 llvm::CallInst *SetJmpResult =
4705 SetJmpBuffer,
"setjmp.result");
4706 SetJmpResult->setCanReturnTwice();
4708 llvm::Value *Threw =
4709 CGF.
Builder.CreateIsNotNull(SetJmpResult,
"did_catch_exception");
4713 CGF.
Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
4723 bool AllMatched =
false;
4725 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
4744 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4751 EmitInitOfCatchParam(CGF, Caught, CatchParam);
4754 CGF.
EmitStmt(CatchStmt->getCatchBody());
4757 CatchVarCleanups.ForceCleanup();
4763 assert(OPT &&
"Unexpected non-object pointer type in @catch");
4768 assert(IDecl &&
"Catch parameter must have Objective-C type!");
4771 llvm::Value *
Class = EmitClassRef(CGF, IDecl);
4773 llvm::Value *matchArgs[] = {
Class, Caught };
4774 llvm::CallInst *Match =
4776 matchArgs,
"match");
4781 CGF.
Builder.CreateCondBr(CGF.
Builder.CreateIsNotNull(Match,
"matched"),
4782 MatchedBlock, NextCatchBlock);
4789 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4796 CGF.
Builder.CreateBitCast(Caught,
4798 EmitInitOfCatchParam(CGF, Tmp, CatchParam);
4800 CGF.
EmitStmt(CatchStmt->getCatchBody());
4803 CatchVarCleanups.ForceCleanup();
4814 if (Caught->use_empty())
4815 Caught->eraseFromParent();
4831 assert(PropagatingExnVar.
isValid());
4832 llvm::CallInst *NewCaught =
4834 ExceptionData.getPointer(),
"caught");
4844 Hazards.emitHazardsInNewBlocks();
4847 CGF.
Builder.restoreIP(TryFallthroughIP);
4851 CGF.
EmitBlock(FinallyEnd.getBlock(),
true);
4854 CGBuilderTy::InsertPoint SavedIP = CGF.
Builder.saveAndClearIP();
4855 CGF.
EmitBlock(FinallyRethrow.getBlock(),
true);
4858 llvm::Value *PropagatingExn;
4859 if (PropagatingExnVar.
isValid()) {
4864 llvm::CallInst *Caught =
4866 ExceptionData.getPointer());
4867 PropagatingExn = Caught;
4872 CGF.
Builder.CreateUnreachable();
4875 CGF.
Builder.restoreIP(SavedIP);
4880 bool ClearInsertionPoint) {
4881 llvm::Value *ExceptionAsObject;
4883 if (
const Expr *ThrowExpr = S.getThrowExpr()) {
4886 CGF.
Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
4889 "Unexpected rethrow outside @catch block.");
4893 CGF.
EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
4894 ->setDoesNotReturn();
4895 CGF.
Builder.CreateUnreachable();
4898 if (ClearInsertionPoint)
4899 CGF.
Builder.ClearInsertionPoint();
4908 llvm::Value *AddrWeakObjVal = CGF.
Builder.CreateBitCast(
4909 AddrWeakObj.
getPointer(), ObjCTypes.PtrObjectPtrTy);
4910 llvm::Value *read_weak =
4912 AddrWeakObjVal,
"weakread");
4913 read_weak = CGF.
Builder.CreateBitCast(read_weak, DestTy);
4921 llvm::Value *src,
Address dst) {
4922 llvm::Type * SrcTy = src->getType();
4923 if (!isa<llvm::PointerType>(SrcTy)) {
4925 assert(Size <= 8 && "does not support size > 8
");
4926 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4927 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4928 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4930 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4931 llvm::Value *dstVal =
4932 CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy);
4933 llvm::Value *args[] = { src, dstVal };
4934 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
4935 args, "weakassign
");
4941void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
4942 llvm::Value *src, Address dst,
4944 llvm::Type * SrcTy = src->getType();
4945 if (!isa<llvm::PointerType>(SrcTy)) {
4946 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4947 assert(Size <= 8 && "does
not support size > 8
");
4948 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4949 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4950 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4952 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4953 llvm::Value *dstVal =
4954 CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy);
4955 llvm::Value *args[] = {src, dstVal};
4957 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
4958 args, "globalassign
");
4960 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
4961 args, "threadlocalassign
");
4967void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
4968 llvm::Value *src, Address dst,
4969 llvm::Value *ivarOffset) {
4970 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is
NULL");
4971 llvm::Type * SrcTy = src->getType();
4972 if (!isa<llvm::PointerType>(SrcTy)) {
4973 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4974 assert(Size <= 8 && "does
not support size > 8
");
4975 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4976 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4977 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4979 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4980 llvm::Value *dstVal =
4981 CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy);
4982 llvm::Value *args[] = {src, dstVal, ivarOffset};
4983 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
4989void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
4990 llvm::Value *src, Address dst) {
4991 llvm::Type * SrcTy = src->getType();
4992 if (!isa<llvm::PointerType>(SrcTy)) {
4993 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4994 assert(Size <= 8 && "does
not support size > 8
");
4995 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4996 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4997 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4999 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5000 llvm::Value *dstVal =
5001 CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy);
5002 llvm::Value *args[] = {src, dstVal};
5003 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
5004 args, "strongassign
");
5007void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
5008 Address DestPtr, Address SrcPtr,
5009 llvm::Value *size) {
5010 llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size };
5011 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
5016LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
5018 llvm::Value *BaseValue,
5019 const ObjCIvarDecl *Ivar,
5020 unsigned CVRQualifiers) {
5021 const ObjCInterfaceDecl *ID =
5022 ObjectTy->castAs<ObjCObjectType>()->getInterface();
5023 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5024 EmitIvarOffset(CGF, ID, Ivar));
5027llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
5028 const ObjCInterfaceDecl *Interface,
5029 const ObjCIvarDecl *Ivar) {
5030 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
5031 return llvm::ConstantInt::get(
5032 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
5036/* *** Private Interface *** */
5038std::string CGObjCCommonMac::GetSectionName(StringRef Section,
5039 StringRef MachOAttributes) {
5040 switch (CGM.getTriple().getObjectFormat()) {
5041 case llvm::Triple::UnknownObjectFormat:
5042 llvm_unreachable("unexpected
object file format
");
5043 case llvm::Triple::MachO: {
5044 if (MachOAttributes.empty())
5045 return ("__DATA,
" + Section).str();
5046 return ("__DATA,
" + Section + ",
" + MachOAttributes).str();
5048 case llvm::Triple::ELF:
5049 assert(Section.starts_with("__
") && "expected the name to begin with __
");
5050 return Section.substr(2).str();
5051 case llvm::Triple::COFF:
5052 assert(Section.starts_with("__
") && "expected the name to begin with __
");
5053 return (".
" + Section.substr(2) + "$B
").str();
5054 case llvm::Triple::Wasm:
5055 case llvm::Triple::GOFF:
5056 case llvm::Triple::SPIRV:
5057 case llvm::Triple::XCOFF:
5058 case llvm::Triple::DXContainer:
5059 llvm::report_fatal_error(
5060 "Objective-
C support is unimplemented
for object file format
");
5063 llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType
enum");
5074enum ImageInfoFlags {
5075 eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
5076 eImageInfo_GarbageCollected = (1 << 1),
5077 eImageInfo_GCOnly = (1 << 2),
5078 eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
5080 // A flag indicating that the module has no instances of a @synthesize of a
5081 // superclass variable. This flag used to be consumed by the runtime to work
5082 // around miscompile by gcc.
5083 eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang.
5084 eImageInfo_ImageIsSimulated = (1 << 5),
5085 eImageInfo_ClassProperties = (1 << 6)
5088void CGObjCCommonMac::EmitImageInfo() {
5089 unsigned version = 0; // Version is unused?
5090 std::string Section =
5092 ? "__OBJC,__image_info,regular
"
5093 : GetSectionName("__objc_imageinfo
", "regular,no_dead_strip
");
5095 // Generate module-level named metadata to convey this information to the
5096 // linker and code-gen.
5097 llvm::Module &Mod = CGM.getModule();
5099 // Add the ObjC ABI version to the module flags.
5100 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Version
", ObjCABI);
5101 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Image Info Version
",
5103 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Image Info Section
",
5104 llvm::MDString::get(VMContext, Section));
5106 auto Int8Ty = llvm::Type::getInt8Ty(VMContext);
5107 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
5108 // Non-GC overrides those files which specify GC.
5109 Mod.addModuleFlag(llvm::Module::Error,
5110 "Objective-
C Garbage Collection
",
5111 llvm::ConstantInt::get(Int8Ty,0));
5113 // Add the ObjC garbage collection value.
5114 Mod.addModuleFlag(llvm::Module::Error,
5115 "Objective-
C Garbage Collection
",
5116 llvm::ConstantInt::get(Int8Ty,
5117 (uint8_t)eImageInfo_GarbageCollected));
5119 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
5120 // Add the ObjC GC Only value.
5121 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C GC Only
",
5124 // Require that GC be specified and set to eImageInfo_GarbageCollected.
5125 llvm::Metadata *Ops[2] = {
5126 llvm::MDString::get(VMContext, "Objective-
C Garbage Collection
"),
5127 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
5128 Int8Ty, eImageInfo_GarbageCollected))};
5129 Mod.addModuleFlag(llvm::Module::Require, "Objective-
C GC Only
",
5130 llvm::MDNode::get(VMContext, Ops));
5134 // Indicate whether we're compiling this to run on a simulator.
5135 if (CGM.getTarget().getTriple().isSimulatorEnvironment())
5136 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Is Simulated
",
5137 eImageInfo_ImageIsSimulated);
5139 // Indicate whether we are generating class properties.
5140 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Class Properties
",
5141 eImageInfo_ClassProperties);
5144// struct objc_module {
5145// unsigned long version;
5146// unsigned long size;
5151// FIXME: Get from somewhere
5152static const int ModuleVersion = 7;
5154void CGObjCMac::EmitModuleInfo() {
5155 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
5157 ConstantInitBuilder builder(CGM);
5158 auto values = builder.beginStruct(ObjCTypes.ModuleTy);
5159 values.addInt(ObjCTypes.LongTy, ModuleVersion);
5160 values.addInt(ObjCTypes.LongTy, Size);
5161 // This used to be the filename, now it is unused. <rdr://4327263>
5162 values.add(GetClassName(StringRef("")));
5163 values.add(EmitModuleSymbols());
5164 CreateMetadataVar("OBJC_MODULES
", values,
5165 "__OBJC,__module_info,regular,no_dead_strip
",
5166 CGM.getPointerAlign(), true);
5169llvm::Constant *CGObjCMac::EmitModuleSymbols() {
5170 unsigned NumClasses = DefinedClasses.size();
5171 unsigned NumCategories = DefinedCategories.size();
5173 // Return null if no symbols were defined.
5174 if (!NumClasses && !NumCategories)
5175 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
5177 ConstantInitBuilder builder(CGM);
5178 auto values = builder.beginStruct();
5179 values.addInt(ObjCTypes.LongTy, 0);
5180 values.addNullPointer(ObjCTypes.SelectorPtrTy);
5181 values.addInt(ObjCTypes.ShortTy, NumClasses);
5182 values.addInt(ObjCTypes.ShortTy, NumCategories);
5184 // The runtime expects exactly the list of defined classes followed
5185 // by the list of defined categories, in a single array.
5186 auto array = values.beginArray(ObjCTypes.Int8PtrTy);
5187 for (unsigned i=0; i<NumClasses; i++) {
5188 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
5190 if (ObjCImplementationDecl *IMP = ID->getImplementation())
5191 // We are implementing a weak imported interface. Give it external linkage
5192 if (ID->isWeakImported() && !IMP->isWeakImported())
5193 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
5195 array.add(DefinedClasses[i]);
5197 for (unsigned i=0; i<NumCategories; i++)
5198 array.add(DefinedCategories[i]);
5200 array.finishAndAddTo(values);
5202 llvm::GlobalVariable *GV = CreateMetadataVar(
5203 "OBJC_SYMBOLS
", values, "__OBJC,__symbols,regular,no_dead_strip
",
5204 CGM.getPointerAlign(), true);
5208llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
5209 IdentifierInfo *II) {
5210 LazySymbols.insert(II);
5212 llvm::GlobalVariable *&Entry = ClassReferences[II];
5216 CreateMetadataVar("OBJC_CLASS_REFERENCES_
", GetClassName(II->getName()),
5217 "__OBJC,__cls_refs,literal_pointers,no_dead_strip
",
5218 CGM.getPointerAlign(), true);
5221 return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry,
5222 CGF.getPointerAlign());
5225llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
5226 const ObjCInterfaceDecl *ID) {
5227 // If the class has the objc_runtime_visible attribute, we need to
5228 // use the Objective-C runtime to get the class.
5229 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
5230 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
5232 IdentifierInfo *RuntimeName =
5233 &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
5234 return EmitClassRefFromId(CGF, RuntimeName);
5237llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
5238 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool
");
5239 return EmitClassRefFromId(CGF, II);
5242llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
5243 return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel));
5246Address CGObjCMac::EmitSelectorAddr(Selector Sel) {
5247 CharUnits Align = CGM.getPointerAlign();
5249 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
5251 Entry = CreateMetadataVar(
5252 "OBJC_SELECTOR_REFERENCES_
", GetMethodVarName(Sel),
5253 "__OBJC,__message_refs,literal_pointers,no_dead_strip
", Align, true);
5254 Entry->setExternallyInitialized(true);
5257 return Address(Entry, ObjCTypes.SelectorPtrTy, Align);
5260llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
5261 llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
5263 Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
5264 return getConstantGEP(VMContext, Entry, 0, 0);
5267llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
5268 return MethodDefinitions.lookup(MD);
5273llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
5274 const ObjCCommonTypesHelper &ObjCTypes) {
5275 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
5278void IvarLayoutBuilder::visitRecord(const RecordType *RT,
5280 const RecordDecl *RD = RT->getDecl();
5282 // If this is a union, remember that we had one, because it might mess
5283 // up the ordering of layout entries.
5285 IsDisordered = true;
5287 const ASTRecordLayout *recLayout = nullptr;
5288 visitAggregate(RD->field_begin(), RD->field_end(), offset,
5289 [&](const FieldDecl *field) -> CharUnits {
5291 recLayout = &CGM.getContext().getASTRecordLayout(RD);
5292 auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex());
5293 return CGM.getContext().toCharUnitsFromBits(offsetInBits);
5297template <class Iterator, class GetOffsetFn>
5298void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
5299 CharUnits aggregateOffset,
5300 const GetOffsetFn &getOffset) {
5301 for (; begin != end; ++begin) {
5302 auto field = *begin;
5304 // Skip over bitfields.
5305 if (field->isBitField()) {
5309 // Compute the offset of the field within the aggregate.
5310 CharUnits fieldOffset = aggregateOffset + getOffset(field);
5312 visitField(field, fieldOffset);
5317void IvarLayoutBuilder::visitField(const FieldDecl *field,
5318 CharUnits fieldOffset) {
5319 QualType fieldType = field->getType();
5321 // Drill down into arrays.
5322 uint64_t numElts = 1;
5323 if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) {
5325 fieldType = arrayType->getElementType();
5327 // Unlike incomplete arrays, constant arrays can be nested.
5328 while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
5329 numElts *= arrayType->getSize().getZExtValue();
5330 fieldType = arrayType->getElementType();
5333 assert(!fieldType->isArrayType() && "ivar of non-constant array
type?
");
5335 // If we ended up with a zero-sized array, we've done what we can do within
5336 // the limits of this layout encoding.
5337 if (numElts == 0) return;
5339 // Recurse if the base element type is a record type.
5340 if (auto recType = fieldType->getAs<RecordType>()) {
5341 size_t oldEnd = IvarsInfo.size();
5343 visitRecord(recType, fieldOffset);
5345 // If we have an array, replicate the first entry's layout information.
5346 auto numEltEntries = IvarsInfo.size() - oldEnd;
5347 if (numElts != 1 && numEltEntries != 0) {
5348 CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
5349 for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
5350 // Copy the last numEltEntries onto the end of the array, adjusting
5351 // each for the element size.
5352 for (size_t i = 0; i != numEltEntries; ++i) {
5353 auto firstEntry = IvarsInfo[oldEnd + i];
5354 IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
5355 firstEntry.SizeInWords));
5363 // Classify the element type.
5364 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
5366 // If it matches what we're looking for, add an entry.
5367 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
5368 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
5369 assert(CGM.getContext().getTypeSizeInChars(fieldType)
5370 == CGM.getPointerSize());
5371 IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
5378llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
5379 llvm::SmallVectorImpl<unsigned char> &buffer) {
5380 // The bitmap is a series of skip/scan instructions, aligned to word
5381 // boundaries. The skip is performed first.
5382 const unsigned char MaxNibble = 0xF;
5383 const unsigned char SkipMask = 0xF0, SkipShift = 4;
5384 const unsigned char ScanMask = 0x0F, ScanShift = 0;
5386 assert(!IvarsInfo.empty() && "generating bitmap
for no data
");
5388 // Sort the ivar info on byte position in case we encounterred a
5389 // union nested in the ivar list.
5391 // This isn't a stable sort, but our algorithm should handle it fine.
5392 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
5394 assert(llvm::is_sorted(IvarsInfo));
5396 assert(IvarsInfo.back().Offset < InstanceEnd);
5398 assert(buffer.empty());
5400 // Skip the next N words.
5401 auto skip = [&](unsigned numWords) {
5402 assert(numWords > 0);
5404 // Try to merge into the previous byte. Since scans happen second, we
5405 // can't do this if it includes a scan.
5406 if (!buffer.empty() && !(buffer.back() & ScanMask)) {
5407 unsigned lastSkip = buffer.back() >> SkipShift;
5408 if (lastSkip < MaxNibble) {
5409 unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
5410 numWords -= claimed;
5411 lastSkip += claimed;
5412 buffer.back() = (lastSkip << SkipShift);
5416 while (numWords >= MaxNibble) {
5417 buffer.push_back(MaxNibble << SkipShift);
5418 numWords -= MaxNibble;
5421 buffer.push_back(numWords << SkipShift);
5425 // Scan the next N words.
5426 auto scan = [&](unsigned numWords) {
5427 assert(numWords > 0);
5429 // Try to merge into the previous byte. Since scans happen second, we can
5430 // do this even if it includes a skip.
5431 if (!buffer.empty()) {
5432 unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
5433 if (lastScan < MaxNibble) {
5434 unsigned claimed = std::min(MaxNibble - lastScan, numWords);
5435 numWords -= claimed;
5436 lastScan += claimed;
5437 buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
5441 while (numWords >= MaxNibble) {
5442 buffer.push_back(MaxNibble << ScanShift);
5443 numWords -= MaxNibble;
5446 buffer.push_back(numWords << ScanShift);
5450 // One past the end of the last scan.
5451 unsigned endOfLastScanInWords = 0;
5452 const CharUnits WordSize = CGM.getPointerSize();
5454 // Consider all the scan requests.
5455 for (auto &request : IvarsInfo) {
5456 CharUnits beginOfScan = request.Offset - InstanceBegin;
5458 // Ignore scan requests that don't start at an even multiple of the
5459 // word size. We can't encode them.
5460 if ((beginOfScan % WordSize) != 0) continue;
5462 // Ignore scan requests that start before the instance start.
5463 // This assumes that scans never span that boundary. The boundary
5464 // isn't the true start of the ivars, because in the fragile-ARC case
5465 // it's rounded up to word alignment, but the test above should leave
5466 // us ignoring that possibility.
5467 if (beginOfScan.isNegative()) {
5468 assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
5472 unsigned beginOfScanInWords = beginOfScan / WordSize;
5473 unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
5475 // If the scan starts some number of words after the last one ended,
5477 if (beginOfScanInWords > endOfLastScanInWords) {
5478 skip(beginOfScanInWords - endOfLastScanInWords);
5480 // Otherwise, start scanning where the last left off.
5482 beginOfScanInWords = endOfLastScanInWords;
5484 // If that leaves us with nothing to scan, ignore this request.
5485 if (beginOfScanInWords >= endOfScanInWords) continue;
5488 // Scan to the end of the request.
5489 assert(beginOfScanInWords < endOfScanInWords);
5490 scan(endOfScanInWords - beginOfScanInWords);
5491 endOfLastScanInWords = endOfScanInWords;
5495 return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
5497 // For GC layouts, emit a skip to the end of the allocation so that we
5498 // have precise information about the entire thing. This isn't useful
5499 // or necessary for the ARC-style layout strings.
5500 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
5501 unsigned lastOffsetInWords =
5502 (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
5503 if (lastOffsetInWords > endOfLastScanInWords) {
5504 skip(lastOffsetInWords - endOfLastScanInWords);
5508 // Null terminate the string.
5509 buffer.push_back(0);
5511 auto *Entry = CGObjC.CreateCStringLiteral(
5512 reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName);
5513 return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
5533CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
5534 CharUnits beginOffset, CharUnits endOffset,
5535 bool ForStrongLayout, bool HasMRCWeakIvars) {
5536 // If this is MRC, and we're either building a strong layout or there
5537 // are no weak ivars, bail out early.
5538 llvm::Type *PtrTy = CGM.Int8PtrTy;
5539 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
5540 !CGM.getLangOpts().ObjCAutoRefCount &&
5541 (ForStrongLayout || !HasMRCWeakIvars))
5542 return llvm::Constant::getNullValue(PtrTy);
5544 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
5545 SmallVector<const ObjCIvarDecl*, 32> ivars;
5547 // GC layout strings include the complete object layout, possibly
5548 // inaccurately in the non-fragile ABI; the runtime knows how to fix this
5551 // ARC layout strings only include the class's ivars. In non-fragile
5552 // runtimes, that means starting at InstanceStart, rounded up to word
5553 // alignment. In fragile runtimes, there's no InstanceStart, so it means
5554 // starting at the offset of the first ivar, rounded up to word alignment.
5556 // MRC weak layout strings follow the ARC style.
5557 CharUnits baseOffset;
5558 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
5559 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
5560 IVD; IVD = IVD->getNextIvar())
5561 ivars.push_back(IVD);
5563 if (isNonFragileABI()) {
5564 baseOffset = beginOffset; // InstanceStart
5565 } else if (!ivars.empty()) {
5567 CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
5569 baseOffset = CharUnits::Zero();
5572 baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
5575 CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
5577 baseOffset = CharUnits::Zero();
5581 return llvm::Constant::getNullValue(PtrTy);
5583 IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
5585 builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
5586 [&](const ObjCIvarDecl *ivar) -> CharUnits {
5587 return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar));
5590 if (!builder.hasBitmapData())
5591 return llvm::Constant::getNullValue(PtrTy);
5593 llvm::SmallVector<unsigned char, 4> buffer;
5594 llvm::Constant *C = builder.buildBitmap(*this, buffer);
5596 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
5597 printf("\n%
s ivar layout
for class '%s':
",
5598 ForStrongLayout ? "strong
" : "weak
",
5599 OMD->getClassInterface()->getName().str().c_str());
5600 builder.dump(buffer);
5605llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
5606 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
5607 // FIXME: Avoid std::string in "Sel.
getAsString()
"
5609 Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
5610 return getConstantGEP(VMContext, Entry, 0, 0);
5613// FIXME: Merge into a single cstring creation function.
5614llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
5615 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
5618llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
5619 std::string TypeStr;
5620 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
5622 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
5624 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
5625 return getConstantGEP(VMContext, Entry, 0, 0);
5628llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
5630 std::string TypeStr =
5631 CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
5633 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
5635 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
5636 return getConstantGEP(VMContext, Entry, 0, 0);
5639// FIXME: Merge into a single cstring creation function.
5640llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
5641 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
5643 Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
5644 return getConstantGEP(VMContext, Entry, 0, 0);
5647// FIXME: Merge into a single cstring creation function.
5648// FIXME: This Decl should be more precise.
5650CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
5651 const Decl *Container) {
5652 std::string TypeStr =
5653 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
5654 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
5657void CGObjCMac::FinishModule() {
5660 // Emit the dummy bodies for any protocols which were referenced but
5662 for (auto &entry : Protocols) {
5663 llvm::GlobalVariable *global = entry.second;
5664 if (global->hasInitializer())
5667 ConstantInitBuilder builder(CGM);
5668 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
5669 values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
5670 values.add(GetClassName(entry.first->getName()));
5671 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
5672 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5673 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5674 values.finishAndSetAsInitializer(global);
5675 CGM.addCompilerUsedGlobal(global);
5678 // Add assembler directives to add lazy undefined symbol references
5679 // for classes which are referenced but not defined. This is
5680 // important for correct linker interaction.
5682 // FIXME: It would be nice if we had an LLVM construct for this.
5683 if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
5684 CGM.getTriple().isOSBinFormatMachO()) {
5685 SmallString<256> Asm;
5686 Asm += CGM.getModule().getModuleInlineAsm();
5687 if (!Asm.empty() && Asm.back() != '\n')
5690 llvm::raw_svector_ostream OS(Asm);
5691 for (const auto *Sym : DefinedSymbols)
5692 OS << "\t.objc_class_name_
" << Sym->getName() << "=0\n
"
5693 << "\t.globl .objc_class_name_
" << Sym->getName() << "\n
";
5694 for (const auto *Sym : LazySymbols)
5695 OS << "\t.lazy_reference .objc_class_name_
" << Sym->getName() << "\n
";
5696 for (const auto &Category : DefinedCategoryNames)
5697 OS << "\t.objc_category_name_
" << Category << "=0\n
"
5698 << "\t.globl .objc_category_name_
" << Category << "\n
";
5700 CGM.getModule().setModuleInlineAsm(OS.str());
5704CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
5705 : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
5706 ObjCEmptyVtableVar(nullptr) {
5712ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
5713 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr)
5715 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5716 ASTContext &Ctx = CGM.getContext();
5717 unsigned ProgramAS = CGM.getDataLayout().getProgramAddressSpace();
5719 ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
5721 LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
5722 Int8PtrTy = CGM.Int8PtrTy;
5723 Int8PtrProgramASTy = llvm::PointerType::get(CGM.Int8Ty, ProgramAS);
5724 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
5726 // arm64 targets use "int" ivar offset variables. All others,
5727 // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
5728 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
5729 IvarOffsetVarTy = IntTy;
5731 IvarOffsetVarTy = LongTy;
5734 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
5736 llvm::PointerType::getUnqual(ObjectPtrTy);
5738 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
5740 // I'm not sure I like this. The implicit coordination is a bit
5741 // gross. We should solve this in a reasonable fashion because this
5742 // is a pretty common task (match some runtime data structure with
5743 // an LLVM data structure).
5745 // FIXME: This is leaked.
5746 // FIXME: Merge with rewriter code?
5748 // struct _objc_super {
5752 RecordDecl *RD = RecordDecl::Create(
5753 Ctx, TagTypeKind::Struct, Ctx.getTranslationUnitDecl(), SourceLocation(),
5754 SourceLocation(), &Ctx.Idents.get("_objc_super
"));
5755 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5756 nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
5757 false, ICIS_NoInit));
5758 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5759 nullptr, Ctx.getObjCClassType(), nullptr,
5760 nullptr, false, ICIS_NoInit));
5761 RD->completeDefinition();
5763 SuperCTy = Ctx.getTagDeclType(RD);
5764 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
5766 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
5767 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
5771 // char *attributes;
5773 PropertyTy = llvm::StructType::create("struct._prop_t
", Int8PtrTy, Int8PtrTy);
5775 // struct _prop_list_t {
5776 // uint32_t entsize; // sizeof(struct _prop_t)
5777 // uint32_t count_of_properties;
5778 // struct _prop_t prop_list[count_of_properties];
5780 PropertyListTy = llvm::StructType::create(
5781 "struct._prop_list_t
", IntTy, IntTy, llvm::ArrayType::get(PropertyTy, 0));
5782 // struct _prop_list_t *
5783 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
5785 // struct _objc_method {
5787 // char *method_type;
5790 MethodTy = llvm::StructType::create("struct._objc_method
", SelectorPtrTy,
5791 Int8PtrTy, Int8PtrProgramASTy);
5793 // struct _objc_cache *
5794 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache
");
5795 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
5798ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
5799 : ObjCCommonTypesHelper(cgm) {
5800 // struct _objc_method_description {
5804 MethodDescriptionTy = llvm::StructType::create(
5805 "struct._objc_method_description
", SelectorPtrTy, Int8PtrTy);
5807 // struct _objc_method_description_list {
5809 // struct _objc_method_description[1];
5811 MethodDescriptionListTy =
5812 llvm::StructType::create("struct._objc_method_description_list
", IntTy,
5813 llvm::ArrayType::get(MethodDescriptionTy, 0));
5815 // struct _objc_method_description_list *
5816 MethodDescriptionListPtrTy =
5817 llvm::PointerType::getUnqual(MethodDescriptionListTy);
5819 // Protocol description structures
5821 // struct _objc_protocol_extension {
5822 // uint32_t size; // sizeof(struct _objc_protocol_extension)
5823 // struct _objc_method_description_list *optional_instance_methods;
5824 // struct _objc_method_description_list *optional_class_methods;
5825 // struct _objc_property_list *instance_properties;
5826 // const char ** extendedMethodTypes;
5827 // struct _objc_property_list *class_properties;
5829 ProtocolExtensionTy = llvm::StructType::create(
5830 "struct._objc_protocol_extension
", IntTy, MethodDescriptionListPtrTy,
5831 MethodDescriptionListPtrTy, PropertyListPtrTy, Int8PtrPtrTy,
5834 // struct _objc_protocol_extension *
5835 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
5837 // Handle recursive construction of Protocol and ProtocolList types
5840 llvm::StructType::create(VMContext, "struct._objc_protocol
");
5843 llvm::StructType::create(VMContext, "struct._objc_protocol_list
");
5844 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy), LongTy,
5845 llvm::ArrayType::get(ProtocolTy, 0));
5847 // struct _objc_protocol {
5848 // struct _objc_protocol_extension *isa;
5849 // char *protocol_name;
5850 // struct _objc_protocol **_objc_protocol_list;
5851 // struct _objc_method_description_list *instance_methods;
5852 // struct _objc_method_description_list *class_methods;
5854 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
5855 llvm::PointerType::getUnqual(ProtocolListTy),
5856 MethodDescriptionListPtrTy, MethodDescriptionListPtrTy);
5858 // struct _objc_protocol_list *
5859 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
5861 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
5863 // Class description structures
5865 // struct _objc_ivar {
5870 IvarTy = llvm::StructType::create("struct._objc_ivar
", Int8PtrTy, Int8PtrTy,
5873 // struct _objc_ivar_list *
5875 llvm::StructType::create(VMContext, "struct._objc_ivar_list
");
5876 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
5878 // struct _objc_method_list *
5880 llvm::StructType::create(VMContext, "struct._objc_method_list
");
5881 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
5883 // struct _objc_class_extension *
5884 ClassExtensionTy = llvm::StructType::create(
5885 "struct._objc_class_extension
", IntTy, Int8PtrTy, PropertyListPtrTy);
5886 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
5888 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class
");
5890 // struct _objc_class {
5892 // Class super_class;
5896 // long instance_size;
5897 // struct _objc_ivar_list *ivars;
5898 // struct _objc_method_list *methods;
5899 // struct _objc_cache *cache;
5900 // struct _objc_protocol_list *protocols;
5901 // char *ivar_layout;
5902 // struct _objc_class_ext *ext;
5904 ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
5905 llvm::PointerType::getUnqual(ClassTy), Int8PtrTy, LongTy,
5906 LongTy, LongTy, IvarListPtrTy, MethodListPtrTy, CachePtrTy,
5907 ProtocolListPtrTy, Int8PtrTy, ClassExtensionPtrTy);
5909 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
5911 // struct _objc_category {
5912 // char *category_name;
5913 // char *class_name;
5914 // struct _objc_method_list *instance_method;
5915 // struct _objc_method_list *class_method;
5916 // struct _objc_protocol_list *protocols;
5917 // uint32_t size; // sizeof(struct _objc_category)
5918 // struct _objc_property_list *instance_properties;// category's @property
5919 // struct _objc_property_list *class_properties;
5921 CategoryTy = llvm::StructType::create(
5922 "struct._objc_category
", Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5923 MethodListPtrTy, ProtocolListPtrTy, IntTy, PropertyListPtrTy,
5926 // Global metadata structures
5928 // struct _objc_symtab {
5929 // long sel_ref_cnt;
5931 // short cls_def_cnt;
5932 // short cat_def_cnt;
5933 // char *defs[cls_def_cnt + cat_def_cnt];
5935 SymtabTy = llvm::StructType::create("struct._objc_symtab
", LongTy,
5936 SelectorPtrTy, ShortTy, ShortTy,
5937 llvm::ArrayType::get(Int8PtrTy, 0));
5938 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
5940 // struct _objc_module {
5942 // long size; // sizeof(struct _objc_module)
5944 // struct _objc_symtab* symtab;
5946 ModuleTy = llvm::StructType::create("struct._objc_module
", LongTy, LongTy,
5947 Int8PtrTy, SymtabPtrTy);
5949 // FIXME: This is the size of the setjmp buffer and should be target
5950 // specific. 18 is what's used on 32-bit X86.
5951 uint64_t SetJmpBufferSize = 18;
5954 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
5956 ExceptionDataTy = llvm::StructType::create(
5957 "struct._objc_exception_data
",
5958 llvm::ArrayType::get(CGM.Int32Ty, SetJmpBufferSize), StackPtrTy);
5961ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
5962 : ObjCCommonTypesHelper(cgm) {
5963 // struct _method_list_t {
5964 // uint32_t entsize; // sizeof(struct _objc_method)
5965 // uint32_t method_count;
5966 // struct _objc_method method_list[method_count];
5969 llvm::StructType::create("struct.__method_list_t
", IntTy, IntTy,
5970 llvm::ArrayType::get(MethodTy, 0));
5971 // struct method_list_t *
5972 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
5974 // struct _protocol_t {
5976 // const char * const protocol_name;
5977 // const struct _protocol_list_t * protocol_list; // super protocols
5978 // const struct method_list_t * const instance_methods;
5979 // const struct method_list_t * const class_methods;
5980 // const struct method_list_t *optionalInstanceMethods;
5981 // const struct method_list_t *optionalClassMethods;
5982 // const struct _prop_list_t * properties;
5983 // const uint32_t size; // sizeof(struct _protocol_t)
5984 // const uint32_t flags; // = 0
5985 // const char ** extendedMethodTypes;
5986 // const char *demangledName;
5987 // const struct _prop_list_t * class_properties;
5990 // Holder for struct _protocol_list_t *
5991 ProtocolListnfABITy =
5992 llvm::StructType::create(VMContext, "struct._objc_protocol_list
");
5994 ProtocolnfABITy = llvm::StructType::create(
5995 "struct._protocol_t
", ObjectPtrTy, Int8PtrTy,
5996 llvm::PointerType::getUnqual(ProtocolListnfABITy), MethodListnfABIPtrTy,
5997 MethodListnfABIPtrTy, MethodListnfABIPtrTy, MethodListnfABIPtrTy,
5998 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy, Int8PtrTy,
6001 // struct _protocol_t*
6002 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
6004 // struct _protocol_list_t {
6005 // long protocol_count; // Note, this is 32/64 bit
6006 // struct _protocol_t *[protocol_count];
6008 ProtocolListnfABITy->setBody(LongTy,
6009 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0));
6011 // struct _objc_protocol_list*
6012 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
6015 // unsigned [long] int *offset; // pointer to ivar offset location
6018 // uint32_t alignment;
6021 IvarnfABITy = llvm::StructType::create(
6022 "struct._ivar_t
", llvm::PointerType::getUnqual(IvarOffsetVarTy),
6023 Int8PtrTy, Int8PtrTy, IntTy, IntTy);
6025 // struct _ivar_list_t {
6026 // uint32 entsize; // sizeof(struct _ivar_t)
6028 // struct _iver_t list[count];
6031 llvm::StructType::create("struct._ivar_list_t
", IntTy, IntTy,
6032 llvm::ArrayType::get(IvarnfABITy, 0));
6034 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
6036 // struct _class_ro_t {
6037 // uint32_t const flags;
6038 // uint32_t const instanceStart;
6039 // uint32_t const instanceSize;
6040 // uint32_t const reserved; // only when building for 64bit targets
6041 // const uint8_t * const ivarLayout;
6042 // const char *const name;
6043 // const struct _method_list_t * const baseMethods;
6044 // const struct _objc_protocol_list *const baseProtocols;
6045 // const struct _ivar_list_t *const ivars;
6046 // const uint8_t * const weakIvarLayout;
6047 // const struct _prop_list_t * const properties;
6050 // FIXME. Add 'reserved' field in 64bit abi mode!
6051 ClassRonfABITy = llvm::StructType::create(
6052 "struct._class_ro_t
", IntTy, IntTy, IntTy, Int8PtrTy, Int8PtrTy,
6053 MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, IvarListnfABIPtrTy,
6054 Int8PtrTy, PropertyListPtrTy);
6056 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
6057 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
6058 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
6061 // struct _class_t {
6062 // struct _class_t *isa;
6063 // struct _class_t * const superclass;
6066 // struct class_ro_t *ro;
6069 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t
");
6070 ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
6071 llvm::PointerType::getUnqual(ClassnfABITy), CachePtrTy,
6072 llvm::PointerType::getUnqual(ImpnfABITy),
6073 llvm::PointerType::getUnqual(ClassRonfABITy));
6075 // LLVM for struct _class_t *
6076 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
6078 // struct _category_t {
6079 // const char * const name;
6080 // struct _class_t *const cls;
6081 // const struct _method_list_t * const instance_methods;
6082 // const struct _method_list_t * const class_methods;
6083 // const struct _protocol_list_t * const protocols;
6084 // const struct _prop_list_t * const properties;
6085 // const struct _prop_list_t * const class_properties;
6086 // const uint32_t size;
6088 CategorynfABITy = llvm::StructType::create(
6089 "struct._category_t
", Int8PtrTy, ClassnfABIPtrTy, MethodListnfABIPtrTy,
6090 MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, PropertyListPtrTy,
6091 PropertyListPtrTy, IntTy);
6093 // New types for nonfragile abi messaging.
6094 CodeGen::CodeGenTypes &Types = CGM.getTypes();
6095 ASTContext &Ctx = CGM.getContext();
6097 // MessageRefTy - LLVM for:
6098 // struct _message_ref_t {
6103 // First the clang type for struct _message_ref_t
6104 RecordDecl *RD = RecordDecl::Create(
6105 Ctx, TagTypeKind::Struct, Ctx.getTranslationUnitDecl(), SourceLocation(),
6106 SourceLocation(), &Ctx.Idents.get("_message_ref_t
"));
6107 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6108 nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false,
6110 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6111 nullptr, Ctx.getObjCSelType(), nullptr, nullptr,
6112 false, ICIS_NoInit));
6113 RD->completeDefinition();
6115 MessageRefCTy = Ctx.getTagDeclType(RD);
6116 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
6117 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
6119 // MessageRefPtrTy - LLVM for struct _message_ref_t*
6120 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
6122 // SuperMessageRefTy - LLVM for:
6123 // struct _super_message_ref_t {
6124 // SUPER_IMP messenger;
6127 SuperMessageRefTy = llvm::StructType::create("struct._super_message_ref_t
",
6128 ImpnfABITy, SelectorPtrTy);
6130 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
6131 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
6134 // struct objc_typeinfo {
6135 // const void** vtable; // objc_ehtype_vtable + 2
6136 // const char* name; // c++ typeinfo string
6139 EHTypeTy = llvm::StructType::create("struct._objc_typeinfo
",
6140 llvm::PointerType::getUnqual(Int8PtrTy),
6141 Int8PtrTy, ClassnfABIPtrTy);
6142 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
6145llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
6146 FinishNonFragileABIModule();
6151void CGObjCNonFragileABIMac::AddModuleClassList(
6152 ArrayRef<llvm::GlobalValue *> Container, StringRef SymbolName,
6153 StringRef SectionName) {
6154 unsigned NumClasses = Container.size();
6159 SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
6160 for (unsigned i=0; i<NumClasses; i++)
6161 Symbols[i] = Container[i];
6163 llvm::Constant *Init =
6164 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
6168 // Section name is obtained by calling GetSectionName, which returns
6169 // sections in the __DATA segment on MachO.
6170 assert((!CGM.getTriple().isOSBinFormatMachO() ||
6171 SectionName.starts_with("__DATA
")) &&
6172 "SectionName expected to start with __DATA on MachO
");
6173 llvm::GlobalVariable *GV = new llvm::GlobalVariable(
6174 CGM.getModule(), Init->getType(), false,
6175 llvm::GlobalValue::PrivateLinkage, Init, SymbolName);
6176 GV->setAlignment(CGM.getDataLayout().getABITypeAlign(Init->getType()));
6177 GV->setSection(SectionName);
6178 CGM.addCompilerUsedGlobal(GV);
6181void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
6182 // nonfragile abi has no module definition.
6184 // Build list of all implemented class addresses in array
6185 // L_OBJC_LABEL_CLASS_$.
6187 for (unsigned i=0, NumClasses=ImplementedClasses.size(); i<NumClasses; i++) {
6188 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
6190 if (ObjCImplementationDecl *IMP = ID->getImplementation())
6191 // We are implementing a weak imported interface. Give it external linkage
6192 if (ID->isWeakImported() && !IMP->isWeakImported()) {
6193 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
6194 DefinedMetaClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
6198 AddModuleClassList(DefinedClasses, "OBJC_LABEL_CLASS_$
",
6199 GetSectionName("__objc_classlist
",
6200 "regular,no_dead_strip
"));
6202 AddModuleClassList(DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$
",
6203 GetSectionName("__objc_nlclslist
",
6204 "regular,no_dead_strip
"));
6206 // Build list of all implemented category addresses in array
6207 // L_OBJC_LABEL_CATEGORY_$.
6208 AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$
",
6209 GetSectionName("__objc_catlist
",
6210 "regular,no_dead_strip
"));
6211 AddModuleClassList(DefinedStubCategories, "OBJC_LABEL_STUB_CATEGORY_$
",
6212 GetSectionName("__objc_catlist2
",
6213 "regular,no_dead_strip
"));
6214 AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$
",
6215 GetSectionName("__objc_nlcatlist
",
6216 "regular,no_dead_strip
"));
6225bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
6226 // At various points we've experimented with using vtable-based
6227 // dispatch for all methods.
6228 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
6229 case CodeGenOptions::Legacy:
6231 case CodeGenOptions::NonLegacy:
6233 case CodeGenOptions::Mixed:
6237 // If so, see whether this selector is in the white-list of things which must
6238 // use the new dispatch convention. We lazily build a dense set for this.
6239 if (VTableDispatchMethods.empty()) {
6240 VTableDispatchMethods.insert(GetNullarySelector("alloc
"));
6241 VTableDispatchMethods.insert(GetNullarySelector("class"));
6242 VTableDispatchMethods.insert(GetNullarySelector("self
"));
6243 VTableDispatchMethods.insert(GetNullarySelector("isFlipped
"));
6244 VTableDispatchMethods.insert(GetNullarySelector("length"));
6245 VTableDispatchMethods.insert(GetNullarySelector("count
"));
6247 // These are vtable-based if GC is disabled.
6248 // Optimistically use vtable dispatch for hybrid compiles.
6249 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
6250 VTableDispatchMethods.insert(GetNullarySelector("retain
"));
6251 VTableDispatchMethods.insert(GetNullarySelector("release
"));
6252 VTableDispatchMethods.insert(GetNullarySelector("autorelease
"));
6255 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone
"));
6256 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass
"));
6257 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector
"));
6258 VTableDispatchMethods.insert(GetUnarySelector("objectForKey
"));
6259 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex
"));
6260 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString
"));
6261 VTableDispatchMethods.insert(GetUnarySelector("isEqual
"));
6263 // These are vtable-based if GC is enabled.
6264 // Optimistically use vtable dispatch for hybrid compiles.
6265 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
6266 VTableDispatchMethods.insert(GetNullarySelector("hash
"));
6267 VTableDispatchMethods.insert(GetUnarySelector("addObject
"));
6269 // "countByEnumeratingWithState:objects:count
"
6270 IdentifierInfo *KeyIdents[] = {
6271 &CGM.getContext().Idents.get("countByEnumeratingWithState
"),
6272 &CGM.getContext().Idents.get("objects
"),
6273 &CGM.getContext().Idents.get("count
")
6275 VTableDispatchMethods.insert(
6276 CGM.getContext().Selectors.getSelector(3, KeyIdents));
6280 return VTableDispatchMethods.count(Sel);
6298llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
6300 unsigned InstanceStart,
6301 unsigned InstanceSize,
6302 const ObjCImplementationDecl *ID) {
6303 std::string ClassName = std::string(ID->getObjCRuntimeNameAsString());
6305 CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
6306 CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
6308 bool hasMRCWeak = false;
6309 if (CGM.getLangOpts().ObjCAutoRefCount)
6310 flags |= NonFragileABI_Class_CompiledByARC;
6311 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
6312 flags |= NonFragileABI_Class_HasMRCWeakIvars;
6314 ConstantInitBuilder builder(CGM);
6315 auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy);
6317 values.addInt(ObjCTypes.IntTy, flags);
6318 values.addInt(ObjCTypes.IntTy, InstanceStart);
6319 values.addInt(ObjCTypes.IntTy, InstanceSize);
6320 values.add((flags & NonFragileABI_Class_Meta)
6321 ? GetIvarLayoutName(nullptr, ObjCTypes)
6322 : BuildStrongIvarLayout(ID, beginInstance, endInstance));
6323 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
6325 // const struct _method_list_t * const baseMethods;
6326 SmallVector<const ObjCMethodDecl*, 16> methods;
6327 if (flags & NonFragileABI_Class_Meta) {
6328 for (const auto *MD : ID->class_methods())
6329 if (!MD->isDirectMethod())
6330 methods.push_back(MD);
6332 for (const auto *MD : ID->instance_methods())
6333 if (!MD->isDirectMethod())
6334 methods.push_back(MD);
6337 values.add(emitMethodList(ID->getObjCRuntimeNameAsString(),
6338 (flags & NonFragileABI_Class_Meta)
6339 ? MethodListType::ClassMethods
6340 : MethodListType::InstanceMethods,
6343 const ObjCInterfaceDecl *OID = ID->getClassInterface();
6344 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer
");
6345 values.add(EmitProtocolList("_OBJC_CLASS_PROTOCOLS_$_
"
6346 + OID->getObjCRuntimeNameAsString(),
6347 OID->all_referenced_protocol_begin(),
6348 OID->all_referenced_protocol_end()));
6350 if (flags & NonFragileABI_Class_Meta) {
6351 values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy);
6352 values.add(GetIvarLayoutName(nullptr, ObjCTypes));
6353 values.add(EmitPropertyList(
6354 "_OBJC_$_CLASS_PROP_LIST_
" + ID->getObjCRuntimeNameAsString(),
6355 ID, ID->getClassInterface(), ObjCTypes, true));
6357 values.add(EmitIvarList(ID));
6358 values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak));
6359 values.add(EmitPropertyList(
6360 "_OBJC_$_PROP_LIST_
" + ID->getObjCRuntimeNameAsString(),
6361 ID, ID->getClassInterface(), ObjCTypes, false));
6364 llvm::SmallString<64> roLabel;
6365 llvm::raw_svector_ostream(roLabel)
6366 << ((flags & NonFragileABI_Class_Meta) ? "_OBJC_METACLASS_RO_$_
"
6367 : "_OBJC_CLASS_RO_$_
")
6370 return finishAndCreateGlobal(values, roLabel, CGM);
6383llvm::GlobalVariable *
6384CGObjCNonFragileABIMac::BuildClassObject(const ObjCInterfaceDecl *CI,
6386 llvm::Constant *IsAGV,
6387 llvm::Constant *SuperClassGV,
6388 llvm::Constant *ClassRoGV,
6389 bool HiddenVisibility) {
6390 ConstantInitBuilder builder(CGM);
6391 auto values = builder.beginStruct(ObjCTypes.ClassnfABITy);
6394 values.add(SuperClassGV);
6396 values.addNullPointer(ObjCTypes.ClassnfABIPtrTy);
6398 values.add(ObjCEmptyCacheVar);
6399 values.add(ObjCEmptyVtableVar);
6400 values.add(ClassRoGV);
6402 llvm::GlobalVariable *GV =
6403 cast<llvm::GlobalVariable>(GetClassGlobal(CI, isMetaclass, ForDefinition));
6404 values.finishAndSetAsInitializer(GV);
6406 if (CGM.getTriple().isOSBinFormatMachO())
6407 GV->setSection("__DATA, __objc_data
");
6408 GV->setAlignment(CGM.getDataLayout().getABITypeAlign(ObjCTypes.ClassnfABITy));
6409 if (!CGM.getTriple().isOSBinFormatCOFF())
6410 if (HiddenVisibility)
6411 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6415bool CGObjCNonFragileABIMac::ImplementationIsNonLazy(
6416 const ObjCImplDecl *OD) const {
6417 return OD->getClassMethod(GetNullarySelector("load
")) != nullptr ||
6418 OD->getClassInterface()->hasAttr<ObjCNonLazyClassAttr>() ||
6419 OD->hasAttr<ObjCNonLazyClassAttr>();
6422void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
6423 uint32_t &InstanceStart,
6424 uint32_t &InstanceSize) {
6425 const ASTRecordLayout &RL =
6426 CGM.getContext().getASTObjCImplementationLayout(OID);
6428 // InstanceSize is really instance end.
6429 InstanceSize = RL.getDataSize().getQuantity();
6431 // If there are no fields, the start is the same as the end.
6432 if (!RL.getFieldCount())
6433 InstanceStart = InstanceSize;
6435 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
6438static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM,
6440 IdentifierInfo &II = CGM.getContext().Idents.get(Name);
6441 TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
6442 DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
6444 const VarDecl *VD = nullptr;
6445 for (const auto *Result : DC->lookup(&II))
6446 if ((VD = dyn_cast<VarDecl>(Result)))
6450 return llvm::GlobalValue::DLLImportStorageClass;
6451 if (VD->hasAttr<DLLExportAttr>())
6452 return llvm::GlobalValue::DLLExportStorageClass;
6453 if (VD->hasAttr<DLLImportAttr>())
6454 return llvm::GlobalValue::DLLImportStorageClass;
6455 return llvm::GlobalValue::DefaultStorageClass;
6458void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
6459 if (!ObjCEmptyCacheVar) {
6461 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CacheTy, false,
6462 llvm::GlobalValue::ExternalLinkage, nullptr,
6463 "_objc_empty_cache
");
6464 if (CGM.getTriple().isOSBinFormatCOFF())
6465 ObjCEmptyCacheVar->setDLLStorageClass(getStorage(CGM, "_objc_empty_cache
"));
6467 // Only OS X with deployment version <10.9 use the empty vtable symbol
6468 const llvm::Triple &Triple = CGM.getTarget().getTriple();
6469 if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9))
6470 ObjCEmptyVtableVar =
6471 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ImpnfABITy, false,
6472 llvm::GlobalValue::ExternalLinkage, nullptr,
6473 "_objc_empty_vtable
");
6475 ObjCEmptyVtableVar =
6476 llvm::ConstantPointerNull::get(ObjCTypes.ImpnfABITy->getPointerTo());
6479 // FIXME: Is this correct (that meta class size is never computed)?
6480 uint32_t InstanceStart =
6481 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
6482 uint32_t InstanceSize = InstanceStart;
6483 uint32_t flags = NonFragileABI_Class_Meta;
6485 llvm::Constant *SuperClassGV, *IsAGV;
6487 const auto *CI = ID->getClassInterface();
6488 assert(CI && "CGObjCNonFragileABIMac::GenerateClass -
class is 0
");
6490 // Build the flags for the metaclass.
6491 bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF())
6492 ? !CI->hasAttr<DLLExportAttr>()
6493 : CI->getVisibility() == HiddenVisibility;
6495 flags |= NonFragileABI_Class_Hidden;
6497 // FIXME: why is this flag set on the metaclass?
6498 // ObjC metaclasses have no fields and don't really get constructed.
6499 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
6500 flags |= NonFragileABI_Class_HasCXXStructors;
6501 if (!ID->hasNonZeroConstructors())
6502 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
6505 if (!CI->getSuperClass()) {
6507 flags |= NonFragileABI_Class_Root;
6509 SuperClassGV = GetClassGlobal(CI, /*metaclass*/ false, NotForDefinition);
6510 IsAGV = GetClassGlobal(CI, /*metaclass*/ true, NotForDefinition);
6512 // Has a root. Current class is not a root.
6513 const ObjCInterfaceDecl *Root = ID->getClassInterface();
6514 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
6517 const auto *Super = CI->getSuperClass();
6518 IsAGV = GetClassGlobal(Root, /*metaclass*/ true, NotForDefinition);
6519 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ true, NotForDefinition);
6522 llvm::GlobalVariable *CLASS_RO_GV =
6523 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
6525 llvm::GlobalVariable *MetaTClass =
6526 BuildClassObject(CI, /*metaclass*/ true,
6527 IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden);
6528 CGM.setGVProperties(MetaTClass, CI);
6529 DefinedMetaClasses.push_back(MetaTClass);
6531 // Metadata for the class
6534 flags |= NonFragileABI_Class_Hidden;
6536 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
6537 flags |= NonFragileABI_Class_HasCXXStructors;
6539 // Set a flag to enable a runtime optimization when a class has
6540 // fields that require destruction but which don't require
6541 // anything except zero-initialization during construction. This
6542 // is most notably true of __strong and __weak types, but you can
6543 // also imagine there being C++ types with non-trivial default
6544 // constructors that merely set all fields to null.
6545 if (!ID->hasNonZeroConstructors())
6546 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
6549 if (hasObjCExceptionAttribute(CGM.getContext(), CI))
6550 flags |= NonFragileABI_Class_Exception;
6552 if (!CI->getSuperClass()) {
6553 flags |= NonFragileABI_Class_Root;
6554 SuperClassGV = nullptr;
6556 // Has a root. Current class is not a root.
6557 const auto *Super = CI->getSuperClass();
6558 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ false, NotForDefinition);
6561 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
6563 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
6565 llvm::GlobalVariable *ClassMD =
6566 BuildClassObject(CI, /*metaclass*/ false,
6567 MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden);
6568 CGM.setGVProperties(ClassMD, CI);
6569 DefinedClasses.push_back(ClassMD);
6570 ImplementedClasses.push_back(CI);
6572 // Determine if this class is also "non-lazy
".
6573 if (ImplementationIsNonLazy(ID))
6574 DefinedNonLazyClasses.push_back(ClassMD);
6576 // Force the definition of the EHType if necessary.
6577 if (flags & NonFragileABI_Class_Exception)
6578 (void) GetInterfaceEHType(CI, ForDefinition);
6579 // Make sure method definition entries are all clear for next implementation.
6580 MethodDefinitions.clear();
6591llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
6592 const ObjCProtocolDecl *PD) {
6594 // This routine is called for @protocol only. So, we must build definition
6595 // of protocol's meta-data (not a reference to it!)
6596 assert(!PD->isNonRuntimeProtocol() &&
6597 "attempting to get a protocol ref to a
static protocol.
");
6598 llvm::Constant *Init = GetOrEmitProtocol(PD);
6600 std::string ProtocolName("_OBJC_PROTOCOL_REFERENCE_$_
");
6601 ProtocolName += PD->getObjCRuntimeNameAsString();
6603 CharUnits Align = CGF.getPointerAlign();
6605 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
6607 return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
6608 PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
6609 llvm::GlobalValue::WeakAnyLinkage, Init,
6611 PTGV->setSection(GetSectionName("__objc_protorefs
",
6612 "coalesced,no_dead_strip
"));
6613 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6614 PTGV->setAlignment(Align.getAsAlign());
6615 if (!CGM.getTriple().isOSBinFormatMachO())
6616 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName));
6617 CGM.addUsedGlobal(PTGV);
6618 return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
6633void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
6634 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
6635 const char *Prefix = "_OBJC_$_CATEGORY_
";
6637 llvm::SmallString<64> ExtCatName(Prefix);
6638 ExtCatName += Interface->getObjCRuntimeNameAsString();
6639 ExtCatName += "_$_
";
6640 ExtCatName += OCD->getNameAsString();
6642 ConstantInitBuilder builder(CGM);
6643 auto values = builder.beginStruct(ObjCTypes.CategorynfABITy);
6644 values.add(GetClassName(OCD->getIdentifier()->getName()));
6645 // meta-class entry symbol
6646 values.add(GetClassGlobal(Interface, /*metaclass*/ false, NotForDefinition));
6647 std::string listName =
6648 (Interface->getObjCRuntimeNameAsString() + "_$_
" + OCD->getName()).str();
6650 SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
6651 SmallVector<const ObjCMethodDecl *, 8> classMethods;
6652 for (const auto *MD : OCD->methods()) {
6653 if (MD->isDirectMethod())
6655 if (MD->isInstanceMethod()) {
6656 instanceMethods.push_back(MD);
6658 classMethods.push_back(MD);
6662 auto instanceMethodList = emitMethodList(
6663 listName, MethodListType::CategoryInstanceMethods, instanceMethods);
6664 auto classMethodList = emitMethodList(
6665 listName, MethodListType::CategoryClassMethods, classMethods);
6666 values.add(instanceMethodList);
6667 values.add(classMethodList);
6668 // Keep track of whether we have actual metadata to emit.
6669 bool isEmptyCategory =
6670 instanceMethodList->isNullValue() && classMethodList->isNullValue();
6672 const ObjCCategoryDecl *Category =
6673 Interface->FindCategoryDeclaration(OCD->getIdentifier());
6675 SmallString<256> ExtName;
6676 llvm::raw_svector_ostream(ExtName)
6677 << Interface->getObjCRuntimeNameAsString() << "_$_
" << OCD->getName();
6679 EmitProtocolList("_OBJC_CATEGORY_PROTOCOLS_$_
" +
6680 Interface->getObjCRuntimeNameAsString() + "_$_
" +
6681 Category->getName(),
6682 Category->protocol_begin(), Category->protocol_end());
6683 auto propertyList = EmitPropertyList("_OBJC_$_PROP_LIST_
" + ExtName.str(),
6684 OCD, Category, ObjCTypes, false);
6685 auto classPropertyList =
6686 EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_
" + ExtName.str(), OCD,
6687 Category, ObjCTypes, true);
6688 values.add(protocolList);
6689 values.add(propertyList);
6690 values.add(classPropertyList);
6691 isEmptyCategory &= protocolList->isNullValue() &&
6692 propertyList->isNullValue() &&
6693 classPropertyList->isNullValue();
6695 values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy);
6696 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
6697 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
6700 if (isEmptyCategory) {
6701 // Empty category, don't emit any metadata.
6703 MethodDefinitions.clear();
6708 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
6709 values.addInt(ObjCTypes.IntTy, Size);
6711 llvm::GlobalVariable *GCATV =
6712 finishAndCreateGlobal(values, ExtCatName.str(), CGM);
6713 CGM.addCompilerUsedGlobal(GCATV);
6714 if (Interface->hasAttr<ObjCClassStubAttr>())
6715 DefinedStubCategories.push_back(GCATV);
6717 DefinedCategories.push_back(GCATV);
6719 // Determine if this category is also "non-lazy
".
6720 if (ImplementationIsNonLazy(OCD))
6721 DefinedNonLazyCategories.push_back(GCATV);
6722 // method definition entries must be clear for next implementation.
6723 MethodDefinitions.clear();
6735void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
6736 const ObjCMethodDecl *MD,
6738 auto method = builder.beginStruct(ObjCTypes.MethodTy);
6739 method.add(GetMethodVarName(MD->getSelector()));
6740 method.add(GetMethodVarType(MD));
6743 // Protocol methods have no implementation. So, this entry is always NULL.
6744 method.addNullPointer(ObjCTypes.Int8PtrProgramASTy);
6746 llvm::Function *fn = GetMethodDefinition(MD);
6747 assert(fn && "no definition
for method?
");
6751 method.finishAndAddTo(builder);
6763CGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind,
6764 ArrayRef<const ObjCMethodDecl *> methods) {
6765 // Return null for empty list.
6766 if (methods.empty())
6767 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
6772 case MethodListType::CategoryInstanceMethods:
6773 prefix = "_OBJC_$_CATEGORY_INSTANCE_METHODS_
";
6774 forProtocol = false;
6776 case MethodListType::CategoryClassMethods:
6777 prefix = "_OBJC_$_CATEGORY_CLASS_METHODS_
";
6778 forProtocol = false;
6780 case MethodListType::InstanceMethods:
6781 prefix = "_OBJC_$_INSTANCE_METHODS_
";
6782 forProtocol = false;
6784 case MethodListType::ClassMethods:
6785 prefix = "_OBJC_$_CLASS_METHODS_
";
6786 forProtocol = false;
6789 case MethodListType::ProtocolInstanceMethods:
6790 prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_
";
6793 case MethodListType::ProtocolClassMethods:
6794 prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_
";
6797 case MethodListType::OptionalProtocolInstanceMethods:
6798 prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_
";
6801 case MethodListType::OptionalProtocolClassMethods:
6802 prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_
";
6807 ConstantInitBuilder builder(CGM);
6808 auto values = builder.beginStruct();
6810 // sizeof(struct _objc_method)
6811 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
6812 values.addInt(ObjCTypes.IntTy, Size);
6814 values.addInt(ObjCTypes.IntTy, methods.size());
6815 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
6816 for (auto MD : methods)
6817 emitMethodConstant(methodArray, MD, forProtocol);
6818 methodArray.finishAndAddTo(values);
6820 llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM);
6821 CGM.addCompilerUsedGlobal(GV);
6827llvm::GlobalVariable *
6828CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6829 const ObjCIvarDecl *Ivar) {
6830 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
6831 llvm::SmallString<64> Name("OBJC_IVAR_$_
");
6832 Name += Container->getObjCRuntimeNameAsString();
6834 Name += Ivar->getName();
6835 llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name);
6836 if (!IvarOffsetGV) {
6838 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.IvarOffsetVarTy,
6839 false, llvm::GlobalValue::ExternalLinkage,
6840 nullptr, Name.str());
6841 if (CGM.getTriple().isOSBinFormatCOFF()) {
6842 bool IsPrivateOrPackage =
6843 Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6844 Ivar->getAccessControl() == ObjCIvarDecl::Package;
6846 const ObjCInterfaceDecl *ContainingID = Ivar->getContainingInterface();
6848 if (ContainingID->hasAttr<DLLImportAttr>())
6850 ->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
6851 else if (ContainingID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage)
6853 ->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
6856 return IvarOffsetGV;
6860CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6861 const ObjCIvarDecl *Ivar,
6862 unsigned long int Offset) {
6863 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
6864 IvarOffsetGV->setInitializer(
6865 llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset));
6866 IvarOffsetGV->setAlignment(
6867 CGM.getDataLayout().getABITypeAlign(ObjCTypes.IvarOffsetVarTy));
6869 if (!CGM.getTriple().isOSBinFormatCOFF()) {
6870 // FIXME: This matches gcc, but shouldn't the visibility be set on the use
6871 // as well (i.e., in ObjCIvarOffsetVariable).
6872 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6873 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
6874 ID->getVisibility() == HiddenVisibility)
6875 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6877 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
6880 // If ID's layout is known, then make the global constant. This serves as a
6881 // useful assertion: we'll never use this variable to calculate ivar offsets,
6882 // so if the runtime tries to patch it then we should crash.
6883 if (isClassLayoutKnownStatically(ID))
6884 IvarOffsetGV->setConstant(true);
6886 if (CGM.getTriple().isOSBinFormatMachO())
6887 IvarOffsetGV->setSection("__DATA, __objc_ivar
");
6888 return IvarOffsetGV;
6908llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
6909 const ObjCImplementationDecl *ID) {
6911 ConstantInitBuilder builder(CGM);
6912 auto ivarList = builder.beginStruct();
6913 ivarList.addInt(ObjCTypes.IntTy,
6914 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy));
6915 auto ivarCountSlot = ivarList.addPlaceholder();
6916 auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy);
6918 const ObjCInterfaceDecl *OID = ID->getClassInterface();
6919 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface
");
6921 // FIXME. Consolidate this with similar code in GenerateClass.
6923 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
6924 IVD; IVD = IVD->getNextIvar()) {
6925 // Ignore unnamed bit-fields.
6926 if (!IVD->getDeclName())
6929 auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy);
6930 ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD,
6931 ComputeIvarBaseOffset(CGM, ID, IVD)));
6932 ivar.add(GetMethodVarName(IVD->getIdentifier()));
6933 ivar.add(GetMethodVarType(IVD));
6934 llvm::Type *FieldTy =
6935 CGM.getTypes().ConvertTypeForMem(IVD->getType());
6936 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
6937 unsigned Align = CGM.getContext().getPreferredTypeAlign(
6938 IVD->getType().getTypePtr()) >> 3;
6939 Align = llvm::Log2_32(Align);
6940 ivar.addInt(ObjCTypes.IntTy, Align);
6941 // NOTE. Size of a bitfield does not match gcc's, because of the
6942 // way bitfields are treated special in each. But I am told that
6943 // 'size' for bitfield ivars is ignored by the runtime so it does
6944 // not matter. If it matters, there is enough info to get the
6946 ivar.addInt(ObjCTypes.IntTy, Size);
6947 ivar.finishAndAddTo(ivars);
6949 // Return null for empty list.
6950 if (ivars.empty()) {
6953 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
6956 auto ivarCount = ivars.size();
6957 ivars.finishAndAddTo(ivarList);
6958 ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount);
6960 const char *Prefix = "_OBJC_$_INSTANCE_VARIABLES_
";
6961 llvm::GlobalVariable *GV = finishAndCreateGlobal(
6962 ivarList, Prefix + OID->getObjCRuntimeNameAsString(), CGM);
6963 CGM.addCompilerUsedGlobal(GV);
6967llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
6968 const ObjCProtocolDecl *PD) {
6969 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
6971 assert(!PD->isNonRuntimeProtocol() &&
6972 "attempting to GetOrEmit a non-runtime protocol
");
6974 // We use the initializer as a marker of whether this is a forward
6975 // reference or not. At module finalization we add the empty
6976 // contents for protocols which were referenced but never defined.
6977 llvm::SmallString<64> Protocol;
6978 llvm::raw_svector_ostream(Protocol) << "_OBJC_PROTOCOL_$_
"
6979 << PD->getObjCRuntimeNameAsString();
6981 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
6982 false, llvm::GlobalValue::ExternalLinkage,
6984 if (!CGM.getTriple().isOSBinFormatMachO())
6985 Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol));
7011llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
7012 const ObjCProtocolDecl *PD) {
7013 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
7015 // Early exit if a defining object has already been generated.
7016 if (Entry && Entry->hasInitializer())
7019 // Use the protocol definition, if there is one.
7020 assert(PD->hasDefinition() &&
7021 "emitting protocol metadata without definition
");
7022 PD = PD->getDefinition();
7024 auto methodLists = ProtocolMethodLists::get(PD);
7026 ConstantInitBuilder builder(CGM);
7027 auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy);
7030 values.addNullPointer(ObjCTypes.ObjectPtrTy);
7031 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
7032 values.add(EmitProtocolList("_OBJC_$_PROTOCOL_REFS_
"
7033 + PD->getObjCRuntimeNameAsString(),
7034 PD->protocol_begin(),
7035 PD->protocol_end()));
7036 values.add(methodLists.emitMethodList(this, PD,
7037 ProtocolMethodLists::RequiredInstanceMethods));
7038 values.add(methodLists.emitMethodList(this, PD,
7039 ProtocolMethodLists::RequiredClassMethods));
7040 values.add(methodLists.emitMethodList(this, PD,
7041 ProtocolMethodLists::OptionalInstanceMethods));
7042 values.add(methodLists.emitMethodList(this, PD,
7043 ProtocolMethodLists::OptionalClassMethods));
7044 values.add(EmitPropertyList(
7045 "_OBJC_$_PROP_LIST_
" + PD->getObjCRuntimeNameAsString(),
7046 nullptr, PD, ObjCTypes, false));
7048 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
7049 values.addInt(ObjCTypes.IntTy, Size);
7050 values.addInt(ObjCTypes.IntTy, 0);
7051 values.add(EmitProtocolMethodTypes("_OBJC_$_PROTOCOL_METHOD_TYPES_
"
7052 + PD->getObjCRuntimeNameAsString(),
7053 methodLists.emitExtendedTypesArray(this),
7056 // const char *demangledName;
7057 values.addNullPointer(ObjCTypes.Int8PtrTy);
7059 values.add(EmitPropertyList(
7060 "_OBJC_$_CLASS_PROP_LIST_
" + PD->getObjCRuntimeNameAsString(),
7061 nullptr, PD, ObjCTypes, true));
7064 // Already created, fix the linkage and update the initializer.
7065 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
7066 values.finishAndSetAsInitializer(Entry);
7068 llvm::SmallString<64> symbolName;
7069 llvm::raw_svector_ostream(symbolName)
7070 << "_OBJC_PROTOCOL_$_
" << PD->getObjCRuntimeNameAsString();
7072 Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(),
7074 llvm::GlobalValue::WeakAnyLinkage);
7075 if (!CGM.getTriple().isOSBinFormatMachO())
7076 Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName));
7078 Protocols[PD->getIdentifier()] = Entry;
7080 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
7081 CGM.addUsedGlobal(Entry);
7083 // Use this protocol meta-data to build protocol list table in section
7084 // __DATA, __objc_protolist
7085 llvm::SmallString<64> ProtocolRef;
7086 llvm::raw_svector_ostream(ProtocolRef) << "_OBJC_LABEL_PROTOCOL_$_
"
7087 << PD->getObjCRuntimeNameAsString();
7089 llvm::GlobalVariable *PTGV =
7090 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
7091 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
7093 if (!CGM.getTriple().isOSBinFormatMachO())
7094 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef));
7096 CGM.getDataLayout().getABITypeAlign(ObjCTypes.ProtocolnfABIPtrTy));
7097 PTGV->setSection(GetSectionName("__objc_protolist
",
7098 "coalesced,no_dead_strip
"));
7099 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
7100 CGM.addUsedGlobal(PTGV);
7113CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
7114 ObjCProtocolDecl::protocol_iterator begin,
7115 ObjCProtocolDecl::protocol_iterator end) {
7116 // Just return null for empty protocol lists
7117 auto Protocols = GetRuntimeProtocolList(begin, end);
7118 if (Protocols.empty())
7119 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
7121 SmallVector<llvm::Constant *, 16> ProtocolRefs;
7122 ProtocolRefs.reserve(Protocols.size());
7124 for (const auto *PD : Protocols)
7125 ProtocolRefs.push_back(GetProtocolRef(PD));
7127 // If all of the protocols in the protocol list are objc_non_runtime_protocol
7129 if (ProtocolRefs.size() == 0)
7130 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
7132 // FIXME: We shouldn't need to do this lookup here, should we?
7133 SmallString<256> TmpName;
7134 Name.toVector(TmpName);
7135 llvm::GlobalVariable *GV =
7136 CGM.getModule().getGlobalVariable(TmpName.str(), true);
7140 ConstantInitBuilder builder(CGM);
7141 auto values = builder.beginStruct();
7142 auto countSlot = values.addPlaceholder();
7144 // A null-terminated array of protocols.
7145 auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy);
7146 for (auto const &proto : ProtocolRefs)
7148 auto count = array.size();
7149 array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy);
7151 array.finishAndAddTo(values);
7152 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
7154 GV = finishAndCreateGlobal(values, Name, CGM);
7155 CGM.addCompilerUsedGlobal(GV);
7165LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
7166 CodeGen::CodeGenFunction &CGF,
7168 llvm::Value *BaseValue,
7169 const ObjCIvarDecl *Ivar,
7170 unsigned CVRQualifiers) {
7171 ObjCInterfaceDecl *ID = ObjectTy->castAs<ObjCObjectType>()->getInterface();
7172 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
7173 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
7178CGObjCNonFragileABIMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
7179 const ObjCInterfaceDecl *Interface,
7180 const ObjCIvarDecl *Ivar) {
7181 llvm::Value *IvarOffsetValue;
7182 if (isClassLayoutKnownStatically(Interface)) {
7183 IvarOffsetValue = llvm::ConstantInt::get(
7184 ObjCTypes.IvarOffsetVarTy,
7185 ComputeIvarBaseOffset(CGM, Interface->getImplementation(), Ivar));
7187 llvm::GlobalVariable *GV = ObjCIvarOffsetVariable(Interface, Ivar);
7189 CGF.Builder.CreateAlignedLoad(GV->getValueType(), GV,
7190 CGF.getSizeAlign(), "ivar
");
7191 if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
7192 cast<llvm::LoadInst>(IvarOffsetValue)
7193 ->setMetadata(llvm::LLVMContext::MD_invariant_load,
7194 llvm::MDNode::get(VMContext, std::nullopt));
7197 // This could be 32bit int or 64bit integer depending on the architecture.
7198 // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
7199 // as this is what caller always expects.
7200 if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
7201 IvarOffsetValue = CGF.Builder.CreateIntCast(
7202 IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv
");
7203 return IvarOffsetValue;
7206static void appendSelectorForMessageRefTable(std::string &buffer,
7207 Selector selector) {
7208 if (selector.isUnarySelector()) {
7209 buffer += selector.getNameForSlot(0);
7213 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
7214 buffer += selector.getNameForSlot(i);
7230CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
7231 ReturnValueSlot returnSlot,
7232 QualType resultType,
7237 const CallArgList &formalArgs,
7238 const ObjCMethodDecl *method) {
7239 // Compute the actual arguments.
7242 // First argument: the receiver / super-call structure.
7244 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
7245 args.add(RValue::get(arg0), arg0Type);
7247 // Second argument: a pointer to the message ref structure. Leave
7248 // the actual argument value blank for now.
7249 args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy);
7251 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
7253 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
7255 NullReturnState nullReturn;
7257 // Find the function to call and the mangled name for the message
7258 // ref structure. Using a different mangled name wouldn't actually
7259 // be a problem; it would just be a waste.
7261 // The runtime currently never uses vtable dispatch for anything
7262 // except normal, non-super message-sends.
7263 // FIXME: don't use this for that.
7264 llvm::FunctionCallee fn = nullptr;
7265 std::string messageRefName("_
");
7266 if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
7268 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
7269 messageRefName += "objc_msgSendSuper2_stret_fixup
";
7271 nullReturn.init(CGF, arg0);
7272 fn = ObjCTypes.getMessageSendStretFixupFn();
7273 messageRefName += "objc_msgSend_stret_fixup
";
7275 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
7276 fn = ObjCTypes.getMessageSendFpretFixupFn();
7277 messageRefName += "objc_msgSend_fpret_fixup
";
7280 fn = ObjCTypes.getMessageSendSuper2FixupFn();
7281 messageRefName += "objc_msgSendSuper2_fixup
";
7283 fn = ObjCTypes.getMessageSendFixupFn();
7284 messageRefName += "objc_msgSend_fixup
";
7287 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend
");
7288 messageRefName += '_';
7290 // Append the selector name, except use underscores anywhere we
7291 // would have used colons.
7292 appendSelectorForMessageRefTable(messageRefName, selector);
7294 llvm::GlobalVariable *messageRef
7295 = CGM.getModule().getGlobalVariable(messageRefName);
7297 // Build the message ref structure.
7298 ConstantInitBuilder builder(CGM);
7299 auto values = builder.beginStruct();
7300 values.add(cast<llvm::Constant>(fn.getCallee()));
7301 values.add(GetMethodVarName(selector));
7302 messageRef = values.finishAndCreateGlobal(messageRefName,
7303 CharUnits::fromQuantity(16),
7305 llvm::GlobalValue::WeakAnyLinkage);
7306 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
7307 messageRef->setSection(GetSectionName("__objc_msgrefs
", "coalesced
"));
7310 bool requiresnullCheck = false;
7311 if (CGM.getLangOpts().ObjCAutoRefCount && method)
7312 for (const auto *ParamDecl : method->parameters()) {
7313 if (ParamDecl->isDestroyedInCallee()) {
7314 if (!nullReturn.NullBB)
7315 nullReturn.init(CGF, arg0);
7316 requiresnullCheck = true;
7322 Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy),
7323 ObjCTypes.MessageRefTy, CGF.getPointerAlign());
7325 // Update the message ref argument.
7326 args[1].setRValue(RValue::get(mref.getPointer()));
7328 // Load the function to call from the message ref table.
7329 Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0);
7330 llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn
");
7332 calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType);
7333 CGCallee callee(CGCalleeInfo(), calleePtr);
7335 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
7336 return nullReturn.complete(CGF, returnSlot, result, resultType, formalArgs,
7337 requiresnullCheck ? method : nullptr);
7342CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
7343 ReturnValueSlot Return,
7344 QualType ResultType,
7346 llvm::Value *Receiver,
7347 const CallArgList &CallArgs,
7348 const ObjCInterfaceDecl *Class,
7349 const ObjCMethodDecl *Method) {
7350 return isVTableDispatchedSelector(Sel)
7351 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
7352 Receiver, CGF.getContext().getObjCIdType(),
7353 false, CallArgs, Method)
7354 : EmitMessageSend(CGF, Return, ResultType, Sel,
7355 Receiver, CGF.getContext().getObjCIdType(),
7356 false, CallArgs, Method, Class, ObjCTypes);
7360CGObjCNonFragileABIMac::GetClassGlobal(const ObjCInterfaceDecl *ID,
7362 ForDefinition_t isForDefinition) {
7364 (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix());
7365 return GetClassGlobal((prefix + ID->getObjCRuntimeNameAsString()).str(),
7367 ID->isWeakImported(),
7369 && CGM.getTriple().isOSBinFormatCOFF()
7370 && ID->hasAttr<DLLImportAttr>());
7374CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name,
7375 ForDefinition_t IsForDefinition,
7376 bool Weak, bool DLLImport) {
7377 llvm::GlobalValue::LinkageTypes L =
7378 Weak ? llvm::GlobalValue::ExternalWeakLinkage
7379 : llvm::GlobalValue::ExternalLinkage;
7381 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
7382 if (!GV || GV->getValueType() != ObjCTypes.ClassnfABITy) {
7383 auto *NewGV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false, L,
7387 NewGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
7390 GV->replaceAllUsesWith(NewGV);
7391 GV->eraseFromParent();
7394 CGM.getModule().insertGlobalVariable(GV);
7397 assert(GV->getLinkage() == L);
7402CGObjCNonFragileABIMac::GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID) {
7403 llvm::Constant *ClassGV = GetClassGlobal(ID, /*metaclass*/ false,
7406 if (!ID->hasAttr<ObjCClassStubAttr>())
7409 ClassGV = llvm::ConstantExpr::getPointerCast(ClassGV, ObjCTypes.Int8PtrTy);
7411 // Stub classes are pointer-aligned. Classrefs pointing at stub classes
7412 // must set the least significant bit set to 1.
7413 auto *Idx = llvm::ConstantInt::get(CGM.Int32Ty, 1);
7414 return llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, ClassGV, Idx);
7418CGObjCNonFragileABIMac::EmitLoadOfClassRef(CodeGenFunction &CGF,
7419 const ObjCInterfaceDecl *ID,
7420 llvm::GlobalVariable *Entry) {
7421 if (ID && ID->hasAttr<ObjCClassStubAttr>()) {
7422 // Classrefs pointing at Objective-C stub classes must be loaded by calling
7423 // a special runtime function.
7424 return CGF.EmitRuntimeCall(
7425 ObjCTypes.getLoadClassrefFn(), Entry, "load_classref_result
");
7428 CharUnits Align = CGF.getPointerAlign();
7429 return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry, Align);
7433CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
7435 const ObjCInterfaceDecl *ID) {
7436 llvm::GlobalVariable *&Entry = ClassReferences[II];
7439 llvm::Constant *ClassGV;
7441 ClassGV = GetClassGlobalForClassRef(ID);
7443 ClassGV = GetClassGlobal((getClassSymbolPrefix() + II->getName()).str(),
7445 assert(ClassGV->getType() == ObjCTypes.ClassnfABIPtrTy &&
7446 "classref was emitted with the wrong
type?
");
7449 std::string SectionName =
7450 GetSectionName("__objc_classrefs
", "regular,no_dead_strip
");
7451 Entry = new llvm::GlobalVariable(
7452 CGM.getModule(), ClassGV->getType(), false,
7453 getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV,
7454 "OBJC_CLASSLIST_REFERENCES_$_
");
7455 Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
7456 if (!ID || !ID->hasAttr<ObjCClassStubAttr>())
7457 Entry->setSection(SectionName);
7459 CGM.addCompilerUsedGlobal(Entry);
7462 return EmitLoadOfClassRef(CGF, ID, Entry);
7465llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
7466 const ObjCInterfaceDecl *ID) {
7467 // If the class has the objc_runtime_visible attribute, we need to
7468 // use the Objective-C runtime to get the class.
7469 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
7470 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
7472 return EmitClassRefFromId(CGF, ID->getIdentifier(), ID);
7475llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
7476 CodeGenFunction &CGF) {
7477 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool
");
7478 return EmitClassRefFromId(CGF, II, nullptr);
7482CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
7483 const ObjCInterfaceDecl *ID) {
7484 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
7487 llvm::Constant *ClassGV = GetClassGlobalForClassRef(ID);
7488 std::string SectionName =
7489 GetSectionName("__objc_superrefs
", "regular,no_dead_strip
");
7490 Entry = new llvm::GlobalVariable(CGM.getModule(), ClassGV->getType(), false,
7491 llvm::GlobalValue::PrivateLinkage, ClassGV,
7492 "OBJC_CLASSLIST_SUP_REFS_$_
");
7493 Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
7494 Entry->setSection(SectionName);
7495 CGM.addCompilerUsedGlobal(Entry);
7498 return EmitLoadOfClassRef(CGF, ID, Entry);
7504llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
7505 const ObjCInterfaceDecl *ID,
7507 CharUnits Align = CGF.getPointerAlign();
7508 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
7510 auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition);
7511 std::string SectionName =
7512 GetSectionName("__objc_superrefs
", "regular,no_dead_strip
");
7513 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
7514 false, llvm::GlobalValue::PrivateLinkage,
7515 MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_
");
7516 Entry->setAlignment(Align.getAsAlign());
7517 Entry->setSection(SectionName);
7518 CGM.addCompilerUsedGlobal(Entry);
7521 return CGF.Builder.CreateAlignedLoad(ObjCTypes.ClassnfABIPtrTy, Entry, Align);
7526llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
7527 const ObjCInterfaceDecl *ID) {
7528 if (ID->isWeakImported()) {
7529 auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
7531 assert(!isa<llvm::GlobalVariable>(ClassGV) ||
7532 cast<llvm::GlobalVariable>(ClassGV)->hasExternalWeakLinkage());
7535 return EmitClassRef(CGF, ID);
7542CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
7543 ReturnValueSlot Return,
7544 QualType ResultType,
7546 const ObjCInterfaceDecl *Class,
7547 bool isCategoryImpl,
7548 llvm::Value *Receiver,
7549 bool IsClassMessage,
7550 const CodeGen::CallArgList &CallArgs,
7551 const ObjCMethodDecl *Method) {
7553 // Create and init a super structure; this is a (receiver, class)
7554 // pair we will pass to objc_msgSendSuper.
7556 CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(),
7559 llvm::Value *ReceiverAsObject =
7560 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
7561 CGF.Builder.CreateStore(ReceiverAsObject,
7562 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
7564 // If this is a class message the metaclass is passed as the target.
7565 llvm::Value *Target;
7567 Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported());
7569 Target = EmitSuperClassRef(CGF, Class);
7571 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
7573 llvm::Type *ClassTy =
7574 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
7575 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
7576 CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
7578 return (isVTableDispatchedSelector(Sel))
7579 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
7580 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
7581 true, CallArgs, Method)
7582 : EmitMessageSend(CGF, Return, ResultType, Sel,
7583 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
7584 true, CallArgs, Method, Class, ObjCTypes);
7587llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
7589 Address Addr = EmitSelectorAddr(Sel);
7591 llvm::LoadInst* LI = CGF.Builder.CreateLoad(Addr);
7592 LI->setMetadata(llvm::LLVMContext::MD_invariant_load,
7593 llvm::MDNode::get(VMContext, std::nullopt));
7597Address CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) {
7598 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
7599 CharUnits Align = CGM.getPointerAlign();
7601 std::string SectionName =
7602 GetSectionName("__objc_selrefs
", "literal_pointers,no_dead_strip
");
7603 Entry = new llvm::GlobalVariable(
7604 CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
7605 getLinkageTypeForObjCMetadata(CGM, SectionName), GetMethodVarName(Sel),
7606 "OBJC_SELECTOR_REFERENCES_
");
7607 Entry->setExternallyInitialized(true);
7608 Entry->setSection(SectionName);
7609 Entry->setAlignment(Align.getAsAlign());
7610 CGM.addCompilerUsedGlobal(Entry);
7613 return Address(Entry, ObjCTypes.SelectorPtrTy, Align);
7619void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
7622 llvm::Value *ivarOffset) {
7623 llvm::Type * SrcTy = src->getType();
7624 if (!isa<llvm::PointerType>(SrcTy)) {
7625 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
7626 assert(Size <= 8 && "does
not support size > 8
");
7627 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7628 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
7629 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7631 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7632 llvm::Value *dstVal =
7633 CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy);
7634 llvm::Value *args[] = {src, dstVal, ivarOffset};
7635 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
7641void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
7642 CodeGen::CodeGenFunction &CGF,
7643 llvm::Value *src, Address dst) {
7644 llvm::Type * SrcTy = src->getType();
7645 if (!isa<llvm::PointerType>(SrcTy)) {
7646 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
7647 assert(Size <= 8 && "does
not support size > 8
");
7648 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7649 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
7650 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7652 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7653 llvm::Value *dstVal =
7654 CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy);
7655 llvm::Value *args[] = {src, dstVal};
7656 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
7657 args, "weakassign
");
7660void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
7661 CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr,
7662 llvm::Value *Size) {
7663 llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), Size };
7664 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
7670llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
7671 CodeGen::CodeGenFunction &CGF,
7672 Address AddrWeakObj) {
7673 llvm::Type *DestTy = AddrWeakObj.getElementType();
7674 llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast(
7675 AddrWeakObj.getPointer(), ObjCTypes.PtrObjectPtrTy);
7676 llvm::Value *read_weak =
7677 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
7678 AddrWeakObjVal, "weakread
");
7679 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
7686void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
7687 llvm::Value *src, Address dst) {
7688 llvm::Type * SrcTy = src->getType();
7689 if (!isa<llvm::PointerType>(SrcTy)) {
7690 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
7691 assert(Size <= 8 && "does
not support size > 8
");
7692 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7693 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
7694 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7696 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7697 llvm::Value *dstVal =
7698 CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy);
7699 llvm::Value *args[] = {src, dstVal};
7700 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
7701 args, "weakassign
");
7707void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
7708 llvm::Value *src, Address dst,
7710 llvm::Type * SrcTy = src->getType();
7711 if (!isa<llvm::PointerType>(SrcTy)) {
7712 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
7713 assert(Size <= 8 && "does
not support size > 8
");
7714 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7715 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
7716 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7718 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7719 llvm::Value *dstVal =
7720 CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy);
7721 llvm::Value *args[] = {src, dstVal};
7723 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
7724 args, "globalassign
");
7726 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
7727 args, "threadlocalassign
");
7731CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
7732 const ObjCAtSynchronizedStmt &S) {
7733 EmitAtSynchronizedStmt(CGF, S, ObjCTypes.getSyncEnterFn(),
7734 ObjCTypes.getSyncExitFn());
7738CGObjCNonFragileABIMac::GetEHType(QualType T) {
7739 // There's a particular fixed type info for 'id'.
7740 if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
7741 auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id
");
7744 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
7745 llvm::GlobalValue::ExternalLinkage, nullptr,
7747 if (CGM.getTriple().isOSBinFormatCOFF())
7748 IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id
"));
7753 // All other types should be Objective-C interface pointer types.
7754 const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
7757 const ObjCInterfaceType *IT = PT->getInterfaceType();
7758 assert(IT && "Invalid
@catch type.
");
7760 return GetInterfaceEHType(IT->getDecl(), NotForDefinition);
7763void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
7764 const ObjCAtTryStmt &S) {
7765 EmitTryCatchStmt(CGF, S, ObjCTypes.getObjCBeginCatchFn(),
7766 ObjCTypes.getObjCEndCatchFn(),
7767 ObjCTypes.getExceptionRethrowFn());
7771void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
7772 const ObjCAtThrowStmt &S,
7773 bool ClearInsertionPoint) {
7774 if (const Expr *ThrowExpr = S.getThrowExpr()) {
7775 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
7776 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
7777 llvm::CallBase *Call =
7778 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception);
7779 Call->setDoesNotReturn();
7781 llvm::CallBase *Call =
7782 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn());
7783 Call->setDoesNotReturn();
7786 CGF.Builder.CreateUnreachable();
7787 if (ClearInsertionPoint)
7788 CGF.Builder.ClearInsertionPoint();
7792CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
7793 ForDefinition_t IsForDefinition) {
7794 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
7795 StringRef ClassName = ID->getObjCRuntimeNameAsString();
7797 // If we don't need a definition, return the entry if found or check
7798 // if we use an external reference.
7799 if (!IsForDefinition) {
7803 // If this type (or a super class) has the __objc_exception__
7804 // attribute, emit an external reference.
7805 if (hasObjCExceptionAttribute(CGM.getContext(), ID)) {
7806 std::string EHTypeName = ("OBJC_EHTYPE_$_
" + ClassName).str();
7807 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
7808 false, llvm::GlobalValue::ExternalLinkage,
7809 nullptr, EHTypeName);
7810 CGM.setGVProperties(Entry, ID);
7815 // Otherwise we need to either make a new entry or fill in the initializer.
7816 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition
");
7818 std::string VTableName = "objc_ehtype_vtable
";
7819 auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName);
7822 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, false,
7823 llvm::GlobalValue::ExternalLinkage, nullptr,
7825 if (CGM.getTriple().isOSBinFormatCOFF())
7826 VTableGV->setDLLStorageClass(getStorage(CGM, VTableName));
7829 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
7830 ConstantInitBuilder builder(CGM);
7831 auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
7833 llvm::ConstantExpr::getInBoundsGetElementPtr(VTableGV->getValueType(),
7834 VTableGV, VTableIdx));
7835 values.add(GetClassName(ClassName));
7836 values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition));
7838 llvm::GlobalValue::LinkageTypes L = IsForDefinition
7839 ? llvm::GlobalValue::ExternalLinkage
7840 : llvm::GlobalValue::WeakAnyLinkage;
7842 values.finishAndSetAsInitializer(Entry);
7843 Entry->setAlignment(CGM.getPointerAlign().getAsAlign());
7845 Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_
" + ClassName,
7846 CGM.getPointerAlign(),
7849 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
7850 CGM.setGVProperties(Entry, ID);
7852 assert(Entry->getLinkage() == L);
7854 if (!CGM.getTriple().isOSBinFormatCOFF())
7855 if (ID->getVisibility() == HiddenVisibility)
7856 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
7858 if (IsForDefinition)
7859 if (CGM.getTriple().isOSBinFormatMachO())
7860 Entry->setSection("__DATA,__objc_const
");
7867CodeGen::CGObjCRuntime *
7868CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
7869 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7870 case ObjCRuntime::FragileMacOSX:
7871 return new CGObjCMac(CGM);
7873 case ObjCRuntime::MacOSX:
7874 case ObjCRuntime::iOS:
7875 case ObjCRuntime::WatchOS:
7876 return new CGObjCNonFragileABIMac(CGM);
7878 case ObjCRuntime::GNUstep:
7879 case ObjCRuntime::GCC:
7880 case ObjCRuntime::ObjFW:
7881 llvm_unreachable("these runtimes are
not Mac runtimes
");
7883 llvm_unreachable("bad runtime
");
Defines the clang::ASTContext interface.
ASTImporterLookupTable & LT
@ 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.
@ kCFTaggedObjectID_Integer
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)
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
Defines the Objective-C statement AST node classes.
__device__ __2f16 float __ockl_bool s
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.
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,...
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const ASTRecordLayout & getASTObjCImplementationLayout(const ObjCImplementationDecl *D) const
Get or compute information about the layout of the specified Objective-C implementation.
const LangOptions & getLangOpts() const
SelectorTable & Selectors
QualType getObjCProtoType() const
Retrieve the type of the Objective-C Protocol class.
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.
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
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.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
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.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Represents a block literal declaration, which is like an unnamed FunctionDecl.
QualType withConst() const
Retrieves a version of this type with const applied.
CharUnits - This is an opaque type for sizes expressed in character units.
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.
llvm::Type * getElementType() const
Return the type of the values stored in this address.
llvm::Value * getPointer() const
unsigned getIndex() const
CharUnits getOffset() const
CGBlockInfo - Information to generate a block literal.
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)
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="")
Address CreateGEP(Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
All available information about a concrete callee.
static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())
Implements runtime-specific code generation functions.
virtual llvm::Constant * BuildByrefLayout(CodeGen::CodeGenModule &CGM, QualType T)=0
Returns an i8* which points to the byref layout information.
static void destroyCalleeDestroyedArguments(CodeGenFunction &CGF, const ObjCMethodDecl *method, const CallArgList &callArgs)
Destroy the callee-destroyed arguments of the given method, if it has any.
virtual llvm::Function * GenerateMethod(const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD)=0
Generate a function preamble for a method with the specified types.
virtual std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM, const CGBlockInfo &blockInfo)
virtual llvm::Constant * BuildGCBlockLayout(CodeGen::CodeGenModule &CGM, const CodeGen::CGBlockInfo &blockInfo)=0
virtual ConstantAddress GenerateConstantString(const StringLiteral *)=0
Generate a constant string object.
virtual void GenerateProtocol(const ObjCProtocolDecl *OPD)=0
Generate the named protocol.
virtual llvm::Constant * BuildRCBlockLayout(CodeGen::CodeGenModule &CGM, const CodeGen::CGBlockInfo &blockInfo)=0
virtual void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn, const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD)=0
Generates prologue for direct Objective-C Methods.
CallArgList - Type for representing both the value and type of arguments in a call.
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...
llvm::Value * EmitFromMemory(llvm::Value *Value, QualType Ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
void PopCleanupBlock(bool FallThroughIsBranchThrough=false)
PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.
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 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.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
SmallVector< llvm::Value *, 8 > ObjCEHValueStack
ObjCEHValueStack - Stack of Objective-C exception values, used for rethrows.
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)
EmitCall - Generate a call of the given function, expecting the given result type,...
JumpDest ReturnBlock
ReturnBlock - Unified return block.
Address getNormalCleanupDestSlot()
llvm::Value * EmitObjCThrowOperand(const Expr *expr)
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
Address NormalCleanupDest
i32s containing the indexes of the cleanup destinations.
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
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.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::Type * ConvertType(QualType T)
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs=std::nullopt)
EmitStmt - Emit the code for the statement.
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
llvm::LLVMContext & getLLVMContext()
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
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.
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, const char *GlobalName=nullptr)
Returns a pointer to a character array containing the literal and a terminating '\0' character.
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
A specialization of Address that requires the address to be an LLVM Constant.
llvm::Constant * getPointer() const
StructBuilder beginStruct(llvm::StructType *ty=nullptr)
A helper class of ConstantInitBuilder, used for building constant array initializers.
The standard implementation of ConstantInitBuilder used in Clang.
A helper class of ConstantInitBuilder, used for building constant struct initializers.
Information for lazily generating a cleanup.
LValue - This represents an lvalue references.
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
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.
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
Decl - This represents one declaration (or definition), e.g.
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
This represents one expression.
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
unsigned getBitWidthValue(const ASTContext &Ctx) const
Computes the bit width of this field, if this is a bit field.
One of these records is kept for each identifier that is lexed.
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.
Represents Objective-C's @catch statement.
Represents Objective-C's @finally statement.
Represents Objective-C's @synchronized statement.
Represents Objective-C's @throw statement.
Represents Objective-C's @try ... @catch ... @finally statement.
const ObjCAtFinallyStmt * getFinallyStmt() const
Retrieve the @finally statement, if any.
catch_range catch_stmts()
ObjCCategoryDecl - Represents a category declaration.
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration.
ObjCCompatibleAliasDecl - Represents alias of a class.
ObjCContainerDecl - Represents a container for method declarations.
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()
ObjCMethodDecl - Represents an instance or class method declaration.
ImplicitParamDecl * getSelfDecl() const
bool hasParamDestroyedInCallee() const
True if the method has a parameter that's destroyed in the callee.
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
ObjCInterfaceDecl * getClassInterface()
Represents a pointer to an Objective C object.
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 a class type in Objective C.
ObjCInterfaceDecl * getInterface() const
Gets the interface declaration for this object type, if the base type really is an interface.
Represents one property declaration in an Objective-C interface.
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.
Represents a struct/union/class.
field_range fields() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
Selector getSelector(unsigned NumArgs, IdentifierInfo **IIV)
Can create any sort of selector.
Smart pointer class that efficiently represents Objective-C method names.
std::string getAsString() const
Derive the full selector name (e.g.
Stmt - This represents one statement.
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
The base class of the type hierarchy.
bool isBlockPointerType() const
CanQualType getCanonicalTypeUnqualified() const
const T * castAs() const
Member-template castAs<specific type>.
bool isObjCQualifiedIdType() const
bool isObjCIdType() const
bool isObjCObjectPointerType() const
bool isObjCQualifiedClassType() const
bool isObjCClassType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Represents a variable declaration or definition.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Decl, BlockDecl > blockDecl
Matches block declarations.
bool Zero(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
@ 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.
Selector GetNullarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing a nullary selector.
@ 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.
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::CallingConv::ID getRuntimeCC() const
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::IntegerType * IntTy
int
llvm::PointerType * Int8PtrTy
llvm::PointerType * UnqualPtrTy
llvm::IntegerType * PtrDiffTy
CharUnits getPointerAlign() const