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;
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,
2069 llvm::Value *ReceiverAsObject =
2070 CGF.
Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
2075 llvm::Type *ClassTyPtr = llvm::PointerType::getUnqual(ObjCTypes.ClassTy);
2077 if (IsClassMessage) {
2078 if (isCategoryImpl) {
2085 Target = EmitClassRef(CGF,
Class->getSuperClass());
2090 llvm::Constant *MetaClassPtr = EmitMetaClassRef(
Class);
2091 llvm::Value *SuperPtr =
2097 }
else if (isCategoryImpl)
2098 Target = EmitClassRef(CGF,
Class->getSuperClass());
2100 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
2107 llvm::Type *ClassTy =
2111 return EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper.
getPointer(),
2112 ObjCTypes.SuperPtrCTy,
true, CallArgs, Method, Class,
2121 llvm::Value *Receiver,
2125 return EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
2127 Method, Class, ObjCTypes);
2141 const ObjCCommonTypesHelper &ObjCTypes) {
2144 llvm::Value *SelValue = llvm::UndefValue::get(Types.ConvertType(selTy));
2148 Arg0 = CGF.
Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
2155 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
2160 "Result type mismatch!");
2162 bool ReceiverCanBeNull =
2163 canMessageReceiverBeNull(CGF, Method, IsSuper, ClassReceiver, Arg0);
2165 bool RequiresNullCheck =
false;
2166 bool RequiresSelValue =
true;
2168 llvm::FunctionCallee
Fn =
nullptr;
2174 RequiresSelValue =
false;
2176 if (ReceiverCanBeNull) RequiresNullCheck =
true;
2177 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
2178 : ObjCTypes.getSendStretFn(IsSuper);
2180 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
2181 : ObjCTypes.getSendFpretFn(IsSuper);
2183 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
2184 : ObjCTypes.getSendFp2retFn(IsSuper);
2189 RequiresNullCheck =
true;
2190 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
2191 : ObjCTypes.getSendFn(IsSuper);
2195 llvm::Constant *BitcastFn = cast<llvm::Constant>(
2196 CGF.
Builder.CreateBitCast(
Fn.getCallee(), MSI.MessengerType));
2201 RequiresNullCheck =
false;
2205 RequiresNullCheck =
true;
2207 NullReturnState nullReturn;
2208 if (RequiresNullCheck) {
2209 nullReturn.init(CGF, Arg0);
2213 if (RequiresSelValue) {
2214 SelValue = GetSelector(CGF, Sel);
2218 llvm::CallBase *CallSite;
2220 RValue rvalue = CGF.
EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
2225 if (Method && Method->
hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
2226 CallSite->setDoesNotReturn();
2229 return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs,
2230 RequiresNullCheck ? Method :
nullptr);
2234 bool pointee =
false) {
2247 switch (ownership) {
2254 llvm_unreachable(
"bad objc ownership");
2262 if (Ctx.
getLangOpts().getGC() != LangOptions::NonGC) {
2274 IvarInfo(
CharUnits offset, uint64_t sizeInWords)
2275 : Offset(offset), SizeInWords(sizeInWords) {}
2278 bool operator<(
const IvarInfo &other)
const {
2279 return Offset < other.Offset;
2284 class IvarLayoutBuilder {
2295 bool ForStrongLayout;
2298 bool IsDisordered =
false;
2304 CharUnits instanceEnd,
bool forStrongLayout)
2305 : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
2306 ForStrongLayout(forStrongLayout) {
2311 template <
class Iterator,
class GetOffsetFn>
2312 void visitAggregate(Iterator begin, Iterator end,
2314 const GetOffsetFn &getOffset);
2322 bool hasBitmapData()
const {
return !IvarsInfo.empty(); }
2324 llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
2328 const unsigned char *
s = buffer.data();
2329 for (
unsigned i = 0, e = buffer.size(); i < e; i++)
2331 printf(
"0x0%x%s",
s[i],
s[i] != 0 ?
", " :
"");
2333 printf(
"0x%x%s",
s[i],
s[i] != 0 ?
", " :
"");
2339llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(
CodeGenModule &CGM,
2342 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2343 if (CGM.
getLangOpts().getGC() == LangOptions::NonGC)
2349 builder.visitBlock(blockInfo);
2351 if (!builder.hasBitmapData())
2355 llvm::Constant *
C = builder.buildBitmap(*
this, buffer);
2356 if (CGM.
getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
2357 printf(
"\n block variable layout for block: ");
2358 builder.dump(buffer);
2364void IvarLayoutBuilder::visitBlock(
const CGBlockInfo &blockInfo) {
2377 for (
const auto &CI :
blockDecl->captures()) {
2378 const VarDecl *variable = CI.getVariable();
2390 if (fieldOffset < lastFieldOffset)
2391 IsDisordered =
true;
2392 lastFieldOffset = fieldOffset;
2396 IvarsInfo.push_back(IvarInfo(fieldOffset, 1));
2400 assert(!
type->isArrayType() &&
"array variable should not be caught");
2402 visitRecord(record, fieldOffset);
2411 IvarsInfo.push_back(IvarInfo(fieldOffset, 1));
2436void CGObjCCommonMac::UpdateRunSkipBlockVars(
bool IsByref,
2442 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
2445 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
2448 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
2451 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
2454 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2459void CGObjCCommonMac::BuildRCRecordLayout(
const llvm::StructLayout *RecLayout,
2464 bool IsUnion = (RD && RD->
isUnion());
2467 const FieldDecl *LastFieldBitfieldOrUnnamed =
nullptr;
2471 if (RecFields.empty())
2475 for (
unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2484 if (!
Field->getIdentifier() ||
Field->isBitField()) {
2485 LastFieldBitfieldOrUnnamed =
Field;
2486 LastBitfieldOrUnnamedOffset = FieldOffset;
2490 LastFieldBitfieldOrUnnamed =
nullptr;
2497 BytePos + FieldOffset, HasUnion);
2502 auto *CArray = cast<ConstantArrayType>(Array);
2503 uint64_t ElCount = CArray->getZExtSize();
2504 assert(CArray &&
"only array with known element size is supported");
2505 FQT = CArray->getElementType();
2507 auto *CArray = cast<ConstantArrayType>(Array);
2508 ElCount *= CArray->getZExtSize();
2509 FQT = CArray->getElementType();
2512 int OldIndex = RunSkipBlockVars.size() - 1;
2514 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset, HasUnion);
2519 for (
int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
2521 for (
int i = OldIndex+1; i <= FirstIndex; ++i)
2522 RunSkipBlockVars.push_back(
2523 RUN_SKIP(RunSkipBlockVars[i].opcode,
2524 RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
2525 RunSkipBlockVars[i].block_var_size));
2533 if (UnionIvarSize > MaxUnionSize) {
2534 MaxUnionSize = UnionIvarSize;
2536 MaxFieldOffset = FieldOffset;
2539 UpdateRunSkipBlockVars(
false,
2540 getBlockCaptureLifetime(FQT, ByrefLayout),
2541 BytePos + FieldOffset,
2546 if (LastFieldBitfieldOrUnnamed) {
2547 if (LastFieldBitfieldOrUnnamed->
isBitField()) {
2551 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
2552 ((BitFieldSize % ByteSizeInBits) != 0);
2554 Size += LastBitfieldOrUnnamedOffset;
2555 UpdateRunSkipBlockVars(
false,
2556 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->
getType(),
2558 BytePos + LastBitfieldOrUnnamedOffset,
2561 assert(!LastFieldBitfieldOrUnnamed->
getIdentifier() &&
"Expected unnamed");
2565 UpdateRunSkipBlockVars(
false,
2566 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->
getType(),
2568 BytePos + LastBitfieldOrUnnamedOffset,
2574 UpdateRunSkipBlockVars(
false,
2575 getBlockCaptureLifetime(MaxField->
getType(), ByrefLayout),
2576 BytePos + MaxFieldOffset,
2580void CGObjCCommonMac::BuildRCBlockVarRecordLayout(
const RecordType *RT,
2587 const llvm::StructLayout *RecLayout =
2588 CGM.
getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
2590 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
2602uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2605 if (Layout.size() <= 3) {
2606 unsigned size = Layout.size();
2607 unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
2609 enum BLOCK_LAYOUT_OPCODE opcode ;
2613 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2614 if (opcode == BLOCK_LAYOUT_STRONG)
2615 strong_word_count = (inst & 0xF)+1;
2619 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2620 if (opcode == BLOCK_LAYOUT_BYREF)
2621 byref_word_count = (inst & 0xF)+1;
2625 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2626 if (opcode == BLOCK_LAYOUT_WEAK)
2627 weak_word_count = (inst & 0xF)+1;
2634 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2635 if (opcode == BLOCK_LAYOUT_STRONG) {
2636 strong_word_count = (inst & 0xF)+1;
2638 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2639 if (opcode == BLOCK_LAYOUT_BYREF)
2640 byref_word_count = (inst & 0xF)+1;
2641 else if (opcode == BLOCK_LAYOUT_WEAK)
2642 weak_word_count = (inst & 0xF)+1;
2646 else if (opcode == BLOCK_LAYOUT_BYREF) {
2647 byref_word_count = (inst & 0xF)+1;
2649 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2650 if (opcode == BLOCK_LAYOUT_WEAK)
2651 weak_word_count = (inst & 0xF)+1;
2661 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2662 if (opcode == BLOCK_LAYOUT_STRONG)
2663 strong_word_count = (inst & 0xF)+1;
2664 else if (opcode == BLOCK_LAYOUT_BYREF)
2665 byref_word_count = (inst & 0xF)+1;
2666 else if (opcode == BLOCK_LAYOUT_WEAK)
2667 weak_word_count = (inst & 0xF)+1;
2679 if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
2683 (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
2685 if (size == count) {
2686 if (strong_word_count)
2687 Result = strong_word_count;
2689 if (byref_word_count)
2690 Result += byref_word_count;
2692 if (weak_word_count)
2693 Result += weak_word_count;
2699llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(
bool ComputeByrefLayout) {
2700 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2701 if (RunSkipBlockVars.empty())
2705 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2709 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2712 unsigned size = RunSkipBlockVars.size();
2713 for (
unsigned i = 0; i < size; i++) {
2714 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2715 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2716 CharUnits end_byte_pos = start_byte_pos;
2719 if (opcode == RunSkipBlockVars[j].opcode) {
2720 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2727 end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2730 RunSkipBlockVars[j].block_var_bytepos -
2731 RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
2732 size_in_bytes += gap;
2735 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2736 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2737 size_in_bytes -= residue_in_bytes;
2738 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2741 unsigned size_in_words = size_in_bytes.
getQuantity() / WordSizeInBytes;
2742 while (size_in_words >= 16) {
2745 unsigned char inst = (opcode << 4) | 0xf;
2746 Layout.push_back(inst);
2747 size_in_words -= 16;
2749 if (size_in_words > 0) {
2752 unsigned char inst = (opcode << 4) | (size_in_words-1);
2753 Layout.push_back(inst);
2756 unsigned char inst =
2757 (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.
getQuantity()-1);
2758 Layout.push_back(inst);
2762 while (!Layout.empty()) {
2763 unsigned char inst = Layout.back();
2764 enum BLOCK_LAYOUT_OPCODE opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2765 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2771 uint64_t Result = InlineLayoutInstruction(Layout);
2775 if (ComputeByrefLayout)
2776 printf(
"\n Inline BYREF variable layout: ");
2778 printf(
"\n Inline block variable layout: ");
2779 printf(
"0x0%" PRIx64
"", Result);
2780 if (
auto numStrong = (Result & 0xF00) >> 8)
2781 printf(
", BL_STRONG:%d", (
int) numStrong);
2782 if (
auto numByref = (Result & 0x0F0) >> 4)
2783 printf(
", BL_BYREF:%d", (
int) numByref);
2784 if (
auto numWeak = (Result & 0x00F) >> 0)
2785 printf(
", BL_WEAK:%d", (
int) numWeak);
2786 printf(
", BL_OPERATOR:0\n");
2788 return llvm::ConstantInt::get(CGM.
IntPtrTy, Result);
2791 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2792 Layout.push_back(inst);
2794 for (
unsigned i = 0, e = Layout.size(); i != e; i++)
2795 BitMap += Layout[i];
2798 if (ComputeByrefLayout)
2799 printf(
"\n Byref variable layout: ");
2801 printf(
"\n Block variable layout: ");
2802 for (
unsigned i = 0, e = BitMap.size(); i != e; i++) {
2803 unsigned char inst = BitMap[i];
2804 enum BLOCK_LAYOUT_OPCODE opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2807 case BLOCK_LAYOUT_OPERATOR:
2811 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2812 printf(
"BL_NON_OBJECT_BYTES:");
2814 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2815 printf(
"BL_NON_OBJECT_WORD:");
2817 case BLOCK_LAYOUT_STRONG:
2820 case BLOCK_LAYOUT_BYREF:
2823 case BLOCK_LAYOUT_WEAK:
2826 case BLOCK_LAYOUT_UNRETAINED:
2827 printf(
"BL_UNRETAINED:");
2832 printf(
"%d", (inst & 0xf) + delta);
2840 auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
2848 bool HasCopyDisposeHelpers) {
2850 for (
const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) {
2851 if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) {
2855 }
else if (HasCopyDisposeHelpers) {
2863 case CGObjCCommonMac::BLOCK_LAYOUT_STRONG:
2866 case CGObjCCommonMac::BLOCK_LAYOUT_BYREF:
2869 case CGObjCCommonMac::BLOCK_LAYOUT_WEAK:
2876 Str += llvm::to_string(R.block_var_bytepos.getQuantity());
2877 Str +=
"l" + llvm::to_string(R.block_var_size.getQuantity());
2882void CGObjCCommonMac::fillRunSkipBlockVars(
CodeGenModule &CGM,
2884 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
2886 RunSkipBlockVars.clear();
2887 bool hasUnion =
false;
2891 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2896 const llvm::StructLayout *layout =
2906 for (
const auto &CI :
blockDecl->captures()) {
2907 const VarDecl *variable = CI.getVariable();
2918 assert(!
type->isArrayType() &&
"array variable should not be caught");
2921 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2929 UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(
type,
false),
2930 fieldOffset, fieldSize);
2937 fillRunSkipBlockVars(CGM, blockInfo);
2938 return getBitmapBlockLayout(
false);
2941std::string CGObjCCommonMac::getRCBlockLayoutStr(
CodeGenModule &CGM,
2943 fillRunSkipBlockVars(CGM, blockInfo);
2949 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
2950 assert(!
T->
isArrayType() &&
"__block array variable should not be caught");
2952 RunSkipBlockVars.clear();
2953 bool hasUnion =
false;
2955 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion,
true );
2956 llvm::Constant *Result = getBitmapBlockLayout(
true);
2957 if (isa<llvm::ConstantInt>(Result))
2958 Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.
Int8PtrTy);
2961 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2971 return GetProtocolRef(PD);
2983 GetOrEmitProtocol(PD);
2986llvm::Constant *CGObjCCommonMac::GetProtocolRef(
const ObjCProtocolDecl *PD) {
2988 return GetOrEmitProtocol(PD);
2990 return GetOrEmitProtocolRef(PD);
2993llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime(
2996 ObjCCommonTypesHelper &ObjCTypes) {
2997 llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn();
2999 llvm::Value *className = CGF.
CGM
3001 ID->getObjCRuntimeNameAsString()))
3005 CGF.
Builder.CreateBitCast(className,
3008 llvm::CallInst *call = CGF.
Builder.CreateCall(lookUpClassFn, className);
3009 call->setDoesNotThrow();
3026 llvm::GlobalVariable *Entry = Protocols[PD->
getIdentifier()];
3029 if (Entry && Entry->hasInitializer())
3041 auto methodLists = ProtocolMethodLists::get(PD);
3044 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
3045 values.add(EmitProtocolExtension(PD, methodLists));
3047 values.add(EmitProtocolList(
"OBJC_PROTOCOL_REFS_" + PD->
getName(),
3049 values.add(methodLists.emitMethodList(
this, PD,
3050 ProtocolMethodLists::RequiredInstanceMethods));
3051 values.add(methodLists.emitMethodList(
this, PD,
3052 ProtocolMethodLists::RequiredClassMethods));
3056 assert(Entry->hasPrivateLinkage());
3057 values.finishAndSetAsInitializer(Entry);
3059 Entry = values.finishAndCreateGlobal(
"OBJC_PROTOCOL_" + PD->
getName(),
3062 llvm::GlobalValue::PrivateLinkage);
3063 Entry->setSection(
"__OBJC,__protocol,regular,no_dead_strip");
3072llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD) {
3073 llvm::GlobalVariable *&Entry = Protocols[PD->
getIdentifier()];
3079 Entry =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ProtocolTy,
3080 false, llvm::GlobalValue::PrivateLinkage,
3081 nullptr,
"OBJC_PROTOCOL_" + PD->
getName());
3082 Entry->setSection(
"__OBJC,__protocol,regular,no_dead_strip");
3084 Entry->setAlignment(llvm::Align(4));
3102 const ProtocolMethodLists &methodLists) {
3103 auto optInstanceMethods =
3104 methodLists.emitMethodList(
this, PD,
3105 ProtocolMethodLists::OptionalInstanceMethods);
3106 auto optClassMethods =
3107 methodLists.emitMethodList(
this, PD,
3108 ProtocolMethodLists::OptionalClassMethods);
3110 auto extendedMethodTypes =
3111 EmitProtocolMethodTypes(
"OBJC_PROTOCOL_METHOD_TYPES_" + PD->
getName(),
3112 methodLists.emitExtendedTypesArray(
this),
3115 auto instanceProperties =
3116 EmitPropertyList(
"OBJC_$_PROP_PROTO_LIST_" + PD->
getName(),
nullptr, PD,
3118 auto classProperties =
3119 EmitPropertyList(
"OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->
getName(),
nullptr,
3120 PD, ObjCTypes,
true);
3123 if (optInstanceMethods->isNullValue() &&
3124 optClassMethods->isNullValue() &&
3125 extendedMethodTypes->isNullValue() &&
3126 instanceProperties->isNullValue() &&
3127 classProperties->isNullValue()) {
3128 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
3132 CGM.
getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
3135 auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
3136 values.addInt(ObjCTypes.IntTy, size);
3137 values.add(optInstanceMethods);
3138 values.add(optClassMethods);
3139 values.add(instanceProperties);
3140 values.add(extendedMethodTypes);
3141 values.add(classProperties);
3144 return CreateMetadataVar(
"_OBJC_PROTOCOLEXT_" + PD->
getName(), values,
3156CGObjCMac::EmitProtocolList(Twine name,
3160 auto PDs = GetRuntimeProtocolList(begin, end);
3162 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
3165 auto values = builder.beginStruct();
3168 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
3171 auto countSlot = values.addPlaceholder();
3173 auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
3174 for (
const auto *Proto : PDs)
3175 refsArray.add(GetProtocolRef(Proto));
3177 auto count = refsArray.size();
3180 refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
3182 refsArray.finishAndAddTo(values);
3183 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
3186 if (CGM.
getTriple().isOSBinFormatMachO())
3187 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3189 llvm::GlobalVariable *GV =
3190 CreateMetadataVar(name, values, section, CGM.
getPointerAlign(),
false);
3198 bool IsClassProperty) {
3200 if (IsClassProperty != PD->isClassProperty())
3204 Properties.push_back(PD);
3223llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
3224 const Decl *Container,
3226 const ObjCCommonTypesHelper &ObjCTypes,
3227 bool IsClassProperty) {
3228 if (IsClassProperty) {
3232 if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
3233 (Triple.isiOS() && Triple.isOSVersionLT(9)))
3234 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3242 for (
auto *PD : ClassExt->properties()) {
3243 if (IsClassProperty != PD->isClassProperty())
3245 if (PD->isDirectProperty())
3248 Properties.push_back(PD);
3252 if (IsClassProperty != PD->isClassProperty())
3258 if (PD->isDirectProperty())
3260 Properties.push_back(PD);
3264 for (
const auto *
P : OID->all_referenced_protocols())
3268 for (
const auto *
P : CD->protocols())
3273 if (Properties.empty())
3274 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3276 unsigned propertySize =
3280 auto values = builder.beginStruct();
3281 values.addInt(ObjCTypes.IntTy, propertySize);
3282 values.addInt(ObjCTypes.IntTy, Properties.size());
3283 auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
3284 for (
auto PD : Properties) {
3285 auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
3287 property.add(GetPropertyTypeString(PD, Container));
3288 property.finishAndAddTo(propertiesArray);
3290 propertiesArray.finishAndAddTo(values);
3293 if (CGM.
getTriple().isOSBinFormatMachO())
3294 Section = (ObjCABI == 2) ?
"__DATA, __objc_const"
3295 :
"__OBJC,__property,regular,no_dead_strip";
3297 llvm::GlobalVariable *GV =
3298 CreateMetadataVar(Name, values, Section, CGM.
getPointerAlign(),
true);
3303CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
3305 const ObjCCommonTypesHelper &ObjCTypes) {
3307 if (MethodTypes.empty())
3308 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
3310 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3311 MethodTypes.size());
3312 llvm::Constant *
Init = llvm::ConstantArray::get(AT, MethodTypes);
3315 if (CGM.
getTriple().isOSBinFormatMachO() && ObjCABI == 2)
3316 Section =
"__DATA, __objc_const";
3318 llvm::GlobalVariable *GV =
3347 llvm::raw_svector_ostream(ExtName) <<
Interface->getName() <<
'_'
3351 auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
3359 for (
const auto *MD : OCD->
methods()) {
3360 if (!MD->isDirectMethod())
3361 Methods[
unsigned(MD->isClassMethod())].push_back(MD);
3364 Values.add(GetClassName(OCD->
getName()));
3365 Values.add(GetClassName(
Interface->getObjCRuntimeNameAsString()));
3366 LazySymbols.insert(
Interface->getIdentifier());
3368 Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
3369 Methods[InstanceMethods]));
3370 Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
3371 Methods[ClassMethods]));
3374 EmitProtocolList(
"OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
3377 Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
3379 Values.addInt(ObjCTypes.IntTy, Size);
3383 Values.add(EmitPropertyList(
"_OBJC_$_PROP_LIST_" + ExtName.str(),
3385 Values.add(EmitPropertyList(
"_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
3388 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3389 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3392 llvm::GlobalVariable *GV =
3393 CreateMetadataVar(
"OBJC_CATEGORY_" + ExtName.str(), Values,
3394 "__OBJC,__category,regular,no_dead_strip",
3396 DefinedCategories.push_back(GV);
3397 DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
3399 MethodDefinitions.clear();
3459 for (
auto *field : recType->getDecl()->fields()) {
3474 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
3477 ID->getClassInterface()->all_declared_ivar_begin();
3478 ivar; ivar = ivar->getNextIvar()) {
3508 DefinedSymbols.insert(RuntimeName);
3510 std::string ClassName =
ID->getNameAsString();
3514 llvm::Constant *Protocols =
3515 EmitProtocolList(
"OBJC_CLASS_PROTOCOLS_" +
ID->getName(),
3516 Interface->all_referenced_protocol_begin(),
3517 Interface->all_referenced_protocol_end());
3519 if (
ID->hasNonZeroConstructors() ||
ID->hasDestructors())
3522 bool hasMRCWeak =
false;
3542 for (
const auto *MD :
ID->methods()) {
3543 if (!MD->isDirectMethod())
3544 Methods[
unsigned(MD->isClassMethod())].push_back(MD);
3547 for (
const auto *PID :
ID->property_impls()) {
3549 if (PID->getPropertyDecl()->isDirectProperty())
3552 if (GetMethodDefinition(MD))
3553 Methods[InstanceMethods].push_back(MD);
3555 if (GetMethodDefinition(MD))
3556 Methods[InstanceMethods].push_back(MD);
3561 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3562 values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
3565 LazySymbols.insert(Super->getIdentifier());
3567 values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
3569 values.addNullPointer(ObjCTypes.ClassPtrTy);
3571 values.add(GetClassName(
ID->getObjCRuntimeNameAsString()));
3573 values.addInt(ObjCTypes.LongTy, 0);
3574 values.addInt(ObjCTypes.LongTy, Flags);
3575 values.addInt(ObjCTypes.LongTy,
Size.getQuantity());
3576 values.add(EmitIvarList(ID,
false));
3577 values.add(emitMethodList(
ID->getName(), MethodListType::InstanceMethods,
3578 Methods[InstanceMethods]));
3580 values.addNullPointer(ObjCTypes.CachePtrTy);
3581 values.add(Protocols);
3583 values.add(EmitClassExtension(ID, Size, hasMRCWeak,
3586 std::string Name(
"OBJC_CLASS_");
3588 const char *Section =
"__OBJC,__class,regular,no_dead_strip";
3590 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3592 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3593 "Forward metaclass reference has incorrect type.");
3594 values.finishAndSetAsInitializer(GV);
3595 GV->setSection(Section);
3599 GV = CreateMetadataVar(Name, values, Section, CGM.
getPointerAlign(),
true);
3600 DefinedClasses.push_back(GV);
3601 ImplementedClasses.push_back(
Interface);
3603 MethodDefinitions.clear();
3607 llvm::Constant *Protocols,
3616 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3626 values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
3628 values.addNullPointer(ObjCTypes.ClassPtrTy);
3630 values.add(GetClassName(
ID->getObjCRuntimeNameAsString()));
3632 values.addInt(ObjCTypes.LongTy, 0);
3633 values.addInt(ObjCTypes.LongTy, Flags);
3634 values.addInt(ObjCTypes.LongTy, Size);
3635 values.add(EmitIvarList(ID,
true));
3636 values.add(emitMethodList(
ID->getName(), MethodListType::ClassMethods,
3639 values.addNullPointer(ObjCTypes.CachePtrTy);
3640 values.add(Protocols);
3642 values.addNullPointer(ObjCTypes.Int8PtrTy);
3647 std::string Name(
"OBJC_METACLASS_");
3648 Name +=
ID->getName();
3651 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3653 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3654 "Forward metaclass reference has incorrect type.");
3655 values.finishAndSetAsInitializer(GV);
3659 llvm::GlobalValue::PrivateLinkage);
3661 GV->setSection(
"__OBJC,__meta_class,regular,no_dead_strip");
3668 std::string Name =
"OBJC_METACLASS_" +
ID->getNameAsString();
3678 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3680 GV =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ClassTy,
false,
3681 llvm::GlobalValue::PrivateLinkage,
nullptr,
3684 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3685 "Forward metaclass reference has incorrect type.");
3690 std::string Name =
"OBJC_CLASS_" +
ID->getNameAsString();
3691 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3694 GV =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ClassTy,
false,
3695 llvm::GlobalValue::PrivateLinkage,
nullptr,
3698 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3699 "Forward class metadata reference has incorrect type.");
3719 llvm::Constant *layout;
3721 layout = llvm::ConstantPointerNull::get(CGM.
Int8PtrTy);
3728 llvm::Constant *propertyList =
3729 EmitPropertyList((isMetaclass ? Twine(
"_OBJC_$_CLASS_PROP_LIST_")
3730 : Twine(
"_OBJC_$_PROP_LIST_"))
3732 ID,
ID->getClassInterface(), ObjCTypes, isMetaclass);
3735 if (layout->isNullValue() && propertyList->isNullValue()) {
3736 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
3740 CGM.
getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
3743 auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
3744 values.addInt(ObjCTypes.IntTy, size);
3746 values.add(propertyList);
3748 return CreateMetadataVar(
"OBJC_CLASSEXT_" +
ID->getName(), values,
3749 "__OBJC,__class_ext,regular,no_dead_strip",
3773 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
3778 auto ivarList = builder.beginStruct();
3779 auto countSlot = ivarList.addPlaceholder();
3780 auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
3785 if (!IVD->getDeclName())
3788 auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
3789 ivar.add(GetMethodVarName(IVD->getIdentifier()));
3790 ivar.add(GetMethodVarType(IVD));
3791 ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
3792 ivar.finishAndAddTo(ivars);
3796 auto count = ivars.size();
3800 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
3803 ivars.finishAndAddTo(ivarList);
3804 ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
3806 llvm::GlobalVariable *GV;
3807 GV = CreateMetadataVar(
"OBJC_INSTANCE_VARIABLES_" +
ID->getName(), ivarList,
3808 "__OBJC,__instance_vars,regular,no_dead_strip",
3821 auto description = builder.
beginStruct(ObjCTypes.MethodDescriptionTy);
3822 description.add(GetMethodVarName(MD->
getSelector()));
3823 description.add(GetMethodVarType(MD));
3824 description.finishAndAddTo(builder);
3836 llvm::Function *fn = GetMethodDefinition(MD);
3837 assert(fn &&
"no definition registered for method");
3839 auto method = builder.
beginStruct(ObjCTypes.MethodTy);
3841 method.add(GetMethodVarType(MD));
3843 method.finishAndAddTo(builder);
3859llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
3863 bool forProtocol =
false;
3865 case MethodListType::CategoryInstanceMethods:
3866 prefix =
"OBJC_CATEGORY_INSTANCE_METHODS_";
3867 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3868 forProtocol =
false;
3870 case MethodListType::CategoryClassMethods:
3871 prefix =
"OBJC_CATEGORY_CLASS_METHODS_";
3872 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3873 forProtocol =
false;
3875 case MethodListType::InstanceMethods:
3876 prefix =
"OBJC_INSTANCE_METHODS_";
3877 section =
"__OBJC,__inst_meth,regular,no_dead_strip";
3878 forProtocol =
false;
3880 case MethodListType::ClassMethods:
3881 prefix =
"OBJC_CLASS_METHODS_";
3882 section =
"__OBJC,__cls_meth,regular,no_dead_strip";
3883 forProtocol =
false;
3885 case MethodListType::ProtocolInstanceMethods:
3886 prefix =
"OBJC_PROTOCOL_INSTANCE_METHODS_";
3887 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3890 case MethodListType::ProtocolClassMethods:
3891 prefix =
"OBJC_PROTOCOL_CLASS_METHODS_";
3892 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3895 case MethodListType::OptionalProtocolInstanceMethods:
3896 prefix =
"OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
3897 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3900 case MethodListType::OptionalProtocolClassMethods:
3901 prefix =
"OBJC_PROTOCOL_CLASS_METHODS_OPT_";
3902 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3908 if (methods.empty())
3909 return llvm::Constant::getNullValue(forProtocol
3910 ? ObjCTypes.MethodDescriptionListPtrTy
3911 : ObjCTypes.MethodListPtrTy);
3918 values.addInt(ObjCTypes.IntTy, methods.size());
3919 auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
3920 for (
auto MD : methods) {
3921 emitMethodDescriptionConstant(methodArray, MD);
3923 methodArray.finishAndAddTo(values);
3925 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3933 values.addNullPointer(ObjCTypes.Int8PtrTy);
3934 values.addInt(ObjCTypes.IntTy, methods.size());
3935 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
3936 for (
auto MD : methods) {
3938 emitMethodConstant(methodArray, MD);
3940 methodArray.finishAndAddTo(values);
3942 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3947llvm::Function *CGObjCCommonMac::GenerateMethod(
const ObjCMethodDecl *OMD,
3949 llvm::Function *Method;
3952 Method = GenerateDirectMethod(OMD, CD);
3954 auto Name = getSymbolNameForMethod(OMD);
3957 llvm::FunctionType *MethodTy =
3958 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
3960 llvm::Function::Create(MethodTy, llvm::GlobalValue::InternalLinkage,
3964 MethodDefinitions.insert(std::make_pair(OMD, Method));
3973 auto I = DirectMethodDefinitions.find(COMD);
3974 llvm::Function *OldFn =
nullptr, *
Fn =
nullptr;
3976 if (I != DirectMethodDefinitions.end()) {
3992 llvm::FunctionType *MethodTy =
3993 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
3996 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
3998 Fn->takeName(OldFn);
3999 OldFn->replaceAllUsesWith(Fn);
4000 OldFn->eraseFromParent();
4005 auto Name = getSymbolNameForMethod(OMD,
false);
4007 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
4009 DirectMethodDefinitions.insert(std::make_pair(COMD, Fn));
4015void CGObjCCommonMac::GenerateDirectMethodPrologue(
4019 bool ReceiverCanBeNull =
true;
4021 auto selfValue = Builder.CreateLoad(selfAddr);
4039 "GenerateDirectMethod() should be called with the Class Interface");
4052 result = GeneratePossiblySpecializedMessageSend(
4060 ReceiverCanBeNull = isWeakLinkedClass(OID);
4063 if (ReceiverCanBeNull) {
4064 llvm::BasicBlock *SelfIsNilBlock =
4066 llvm::BasicBlock *ContBlock =
4070 auto selfTy = cast<llvm::PointerType>(selfValue->getType());
4071 auto Zero = llvm::ConstantPointerNull::get(selfTy);
4074 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero), SelfIsNilBlock,
4075 ContBlock, MDHelper.createUnlikelyBranchWeights());
4081 Builder.SetInsertPoint(SelfIsNilBlock);
4082 if (!retTy->isVoidType()) {
4090 Builder.SetInsertPoint(ContBlock);
4098 Builder.CreateStore(GetSelector(CGF, OMD),
4103llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
4108 llvm::GlobalValue::LinkageTypes
LT =
4110 llvm::GlobalVariable *GV =
4111 Init.finishAndCreateGlobal(Name, Align,
false,
LT);
4112 if (!Section.empty())
4113 GV->setSection(Section);
4119llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
4120 llvm::Constant *
Init,
4124 llvm::Type *Ty =
Init->getType();
4125 llvm::GlobalValue::LinkageTypes
LT =
4127 llvm::GlobalVariable *GV =
4129 if (!Section.empty())
4130 GV->setSection(Section);
4137llvm::GlobalVariable *
4138CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType
Type,
4139 bool ForceNonFragileABI,
4140 bool NullTerminate) {
4143 case ObjCLabelType::ClassName:
Label =
"OBJC_CLASS_NAME_";
break;
4144 case ObjCLabelType::MethodVarName:
Label =
"OBJC_METH_VAR_NAME_";
break;
4145 case ObjCLabelType::MethodVarType:
Label =
"OBJC_METH_VAR_TYPE_";
break;
4146 case ObjCLabelType::PropertyName:
Label =
"OBJC_PROP_NAME_ATTR_";
break;
4149 bool NonFragile = ForceNonFragileABI || isNonFragileABI();
4153 case ObjCLabelType::ClassName:
4154 Section = NonFragile ?
"__TEXT,__objc_classname,cstring_literals"
4155 :
"__TEXT,__cstring,cstring_literals";
4157 case ObjCLabelType::MethodVarName:
4158 Section = NonFragile ?
"__TEXT,__objc_methname,cstring_literals"
4159 :
"__TEXT,__cstring,cstring_literals";
4161 case ObjCLabelType::MethodVarType:
4162 Section = NonFragile ?
"__TEXT,__objc_methtype,cstring_literals"
4163 :
"__TEXT,__cstring,cstring_literals";
4165 case ObjCLabelType::PropertyName:
4166 Section = NonFragile ?
"__TEXT,__objc_methname,cstring_literals"
4167 :
"__TEXT,__cstring,cstring_literals";
4171 llvm::Constant *
Value =
4172 llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
4173 llvm::GlobalVariable *GV =
4176 llvm::GlobalValue::PrivateLinkage,
Value,
Label);
4177 if (CGM.
getTriple().isOSBinFormatMachO())
4178 GV->setSection(Section);
4179 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4186llvm::Function *CGObjCMac::ModuleInitFunction() {
4192llvm::FunctionCallee CGObjCMac::GetPropertyGetFunction() {
4193 return ObjCTypes.getGetPropertyFn();
4196llvm::FunctionCallee CGObjCMac::GetPropertySetFunction() {
4197 return ObjCTypes.getSetPropertyFn();
4200llvm::FunctionCallee CGObjCMac::GetOptimizedPropertySetFunction(
bool atomic,
4202 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
4205llvm::FunctionCallee CGObjCMac::GetGetStructFunction() {
4206 return ObjCTypes.getCopyStructFn();
4209llvm::FunctionCallee CGObjCMac::GetSetStructFunction() {
4210 return ObjCTypes.getCopyStructFn();
4213llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectGetFunction() {
4214 return ObjCTypes.getCppAtomicObjectFunction();
4217llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectSetFunction() {
4218 return ObjCTypes.getCppAtomicObjectFunction();
4221llvm::FunctionCallee CGObjCMac::EnumerationMutationFunction() {
4222 return ObjCTypes.getEnumerationMutationFn();
4226 return EmitTryOrSynchronizedStmt(CGF, S);
4231 return EmitTryOrSynchronizedStmt(CGF, S);
4240 ObjCTypesHelper &ObjCTypes;
4241 PerformFragileFinally(
const Stmt *S,
4245 ObjCTypesHelper *ObjCTypes)
4246 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
4247 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
4252 llvm::BasicBlock *FinallyCallExit =
4254 llvm::BasicBlock *FinallyNoCallExit =
4257 FinallyCallExit, FinallyNoCallExit);
4265 if (isa<ObjCAtTryStmt>(S)) {
4267 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
4269 if (flags.isForEHCleanup())
return;
4273 llvm::Value *CurCleanupDest =
4276 CGF.
EmitStmt(FinallyStmt->getFinallyBody());
4295 class FragileHazards {
4300 llvm::InlineAsm *ReadHazard;
4301 llvm::InlineAsm *WriteHazard;
4303 llvm::FunctionType *GetAsmFnType();
4305 void collectLocals();
4311 void emitWriteHazard();
4312 void emitHazardsInNewBlocks();
4324 if (Locals.empty())
return;
4327 for (llvm::Function::iterator
4328 I = CGF.
CurFn->begin(),
E = CGF.
CurFn->end(); I !=
E; ++I)
4329 BlocksBeforeTry.insert(&*I);
4331 llvm::FunctionType *AsmFnTy = GetAsmFnType();
4339 std::string Constraint;
4340 for (
unsigned I = 0,
E = Locals.size(); I !=
E; ++I) {
4341 if (I) Constraint +=
',';
4345 ReadHazard = llvm::InlineAsm::get(AsmFnTy,
"", Constraint,
true,
false);
4353 std::string Constraint;
4354 for (
unsigned I = 0,
E = Locals.size(); I !=
E; ++I) {
4355 if (I) Constraint +=
',';
4356 Constraint +=
"=*m";
4359 WriteHazard = llvm::InlineAsm::get(AsmFnTy,
"", Constraint,
true,
false);
4364void FragileHazards::emitWriteHazard() {
4365 if (Locals.empty())
return;
4368 for (
auto Pair : llvm::enumerate(Locals))
4369 Call->addParamAttr(Pair.index(), llvm::Attribute::get(
4371 cast<llvm::AllocaInst>(Pair.value())->getAllocatedType()));
4374void FragileHazards::emitReadHazard(
CGBuilderTy &Builder) {
4375 assert(!Locals.empty());
4376 llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
4377 call->setDoesNotThrow();
4379 for (
auto Pair : llvm::enumerate(Locals))
4380 call->addParamAttr(Pair.index(), llvm::Attribute::get(
4381 Builder.getContext(), llvm::Attribute::ElementType,
4382 cast<llvm::AllocaInst>(Pair.value())->getAllocatedType()));
4387void FragileHazards::emitHazardsInNewBlocks() {
4388 if (Locals.empty())
return;
4393 for (llvm::Function::iterator
4394 FI = CGF.
CurFn->begin(), FE = CGF.
CurFn->end(); FI != FE; ++FI) {
4395 llvm::BasicBlock &BB = *FI;
4396 if (BlocksBeforeTry.count(&BB))
continue;
4399 for (llvm::BasicBlock::iterator
4400 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
4401 llvm::Instruction &I = *BI;
4405 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I))
4407 if (isa<llvm::IntrinsicInst>(I))
4412 if (cast<llvm::CallBase>(I).doesNotThrow())
4420 Builder.SetInsertPoint(&BB, BI);
4421 emitReadHazard(Builder);
4428 if (llvm::Value *Ptr =
V.getBasePointer())
4432void FragileHazards::collectLocals() {
4440 llvm::BasicBlock &Entry = CGF.
CurFn->getEntryBlock();
4441 for (llvm::BasicBlock::iterator
4442 I = Entry.begin(),
E = Entry.end(); I !=
E; ++I)
4443 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
4444 Locals.push_back(&*I);
4447llvm::FunctionType *FragileHazards::GetAsmFnType() {
4449 for (
unsigned i = 0, e = Locals.size(); i != e; ++i)
4450 tys[i] = Locals[i]->getType();
4451 return llvm::FunctionType::get(CGF.
VoidTy, tys,
false);
4564 bool isTry = isa<ObjCAtTryStmt>(S);
4568 CodeGenFunction::JumpDest FinallyEnd =
4573 CodeGenFunction::JumpDest FinallyRethrow =
4583 llvm::Value *SyncArg =
4584 CGF.
EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
4585 SyncArg = CGF.
Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
4597 "exceptiondata.ptr");
4603 FragileHazards Hazards(CGF);
4632 ExceptionData.emitRawPointer(CGF));
4635 llvm::Constant *
Zero = llvm::ConstantInt::get(CGF.
Builder.getInt32Ty(), 0);
4638 ObjCTypes.ExceptionDataTy, ExceptionData.emitRawPointer(CGF), GEPIndexes,
4641 ObjCTypes.getSetJmpFn(), SetJmpBuffer,
"setjmp_result");
4642 SetJmpResult->setCanReturnTwice();
4648 llvm::Value *DidCatch =
4649 CGF.
Builder.CreateIsNotNull(SetJmpResult,
"did_catch_exception");
4650 CGF.
Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
4655 CGF.
EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
4656 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
4658 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.
Builder.saveAndClearIP();
4664 Hazards.emitWriteHazard();
4668 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
4678 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF),
4689 llvm::BasicBlock *CatchBlock =
nullptr;
4690 llvm::BasicBlock *CatchHandler =
nullptr;
4696 "propagating_exception");
4702 ExceptionData.emitRawPointer(CGF));
4704 llvm::CallInst *SetJmpResult =
4706 SetJmpBuffer,
"setjmp.result");
4707 SetJmpResult->setCanReturnTwice();
4709 llvm::Value *Threw =
4710 CGF.
Builder.CreateIsNotNull(SetJmpResult,
"did_catch_exception");
4714 CGF.
Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
4724 bool AllMatched =
false;
4726 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
4745 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4752 EmitInitOfCatchParam(CGF, Caught, CatchParam);
4755 CGF.
EmitStmt(CatchStmt->getCatchBody());
4758 CatchVarCleanups.ForceCleanup();
4764 assert(OPT &&
"Unexpected non-object pointer type in @catch");
4769 assert(IDecl &&
"Catch parameter must have Objective-C type!");
4772 llvm::Value *
Class = EmitClassRef(CGF, IDecl);
4774 llvm::Value *matchArgs[] = {
Class, Caught };
4775 llvm::CallInst *Match =
4777 matchArgs,
"match");
4782 CGF.
Builder.CreateCondBr(CGF.
Builder.CreateIsNotNull(Match,
"matched"),
4783 MatchedBlock, NextCatchBlock);
4790 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4797 CGF.
Builder.CreateBitCast(Caught,
4799 EmitInitOfCatchParam(CGF, Tmp, CatchParam);
4801 CGF.
EmitStmt(CatchStmt->getCatchBody());
4804 CatchVarCleanups.ForceCleanup();
4815 if (Caught->use_empty())
4816 Caught->eraseFromParent();
4832 assert(PropagatingExnVar.
isValid());
4834 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF),
4845 Hazards.emitHazardsInNewBlocks();
4848 CGF.
Builder.restoreIP(TryFallthroughIP);
4852 CGF.
EmitBlock(FinallyEnd.getBlock(),
true);
4855 CGBuilderTy::InsertPoint SavedIP = CGF.
Builder.saveAndClearIP();
4856 CGF.
EmitBlock(FinallyRethrow.getBlock(),
true);
4859 llvm::Value *PropagatingExn;
4860 if (PropagatingExnVar.
isValid()) {
4866 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF));
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(
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 = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4932 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 = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4954 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 = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4981 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 = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
5001 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.emitRawPointer(CGF),
5011 SrcPtr.emitRawPointer(CGF), size};
5012 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
5017LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
5019 llvm::Value *BaseValue,
5020 const ObjCIvarDecl *Ivar,
5021 unsigned CVRQualifiers) {
5022 const ObjCInterfaceDecl *ID =
5023 ObjectTy->castAs<ObjCObjectType>()->getInterface();
5024 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5025 EmitIvarOffset(CGF, ID, Ivar));
5028llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
5029 const ObjCInterfaceDecl *Interface,
5030 const ObjCIvarDecl *Ivar) {
5031 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
5032 return llvm::ConstantInt::get(
5033 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
5037/* *** Private Interface *** */
5039std::string CGObjCCommonMac::GetSectionName(StringRef Section,
5040 StringRef MachOAttributes) {
5041 switch (CGM.getTriple().getObjectFormat()) {
5042 case llvm::Triple::UnknownObjectFormat:
5043 llvm_unreachable("unexpected
object file format
");
5044 case llvm::Triple::MachO: {
5045 if (MachOAttributes.empty())
5046 return ("__DATA,
" + Section).str();
5047 return ("__DATA,
" + Section + ",
" + MachOAttributes).str();
5049 case llvm::Triple::ELF:
5050 assert(Section.starts_with("__
") && "expected the name to begin with __
");
5051 return Section.substr(2).str();
5052 case llvm::Triple::COFF:
5053 assert(Section.starts_with("__
") && "expected the name to begin with __
");
5054 return (".
" + Section.substr(2) + "$B
").str();
5055 case llvm::Triple::Wasm:
5056 case llvm::Triple::GOFF:
5057 case llvm::Triple::SPIRV:
5058 case llvm::Triple::XCOFF:
5059 case llvm::Triple::DXContainer:
5060 llvm::report_fatal_error(
5061 "Objective-
C support is unimplemented
for object file format
");
5064 llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType
enum");
5075enum ImageInfoFlags {
5076 eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
5077 eImageInfo_GarbageCollected = (1 << 1),
5078 eImageInfo_GCOnly = (1 << 2),
5079 eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
5081 // A flag indicating that the module has no instances of a @synthesize of a
5082 // superclass variable. This flag used to be consumed by the runtime to work
5083 // around miscompile by gcc.
5084 eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang.
5085 eImageInfo_ImageIsSimulated = (1 << 5),
5086 eImageInfo_ClassProperties = (1 << 6)
5089void CGObjCCommonMac::EmitImageInfo() {
5090 unsigned version = 0; // Version is unused?
5091 std::string Section =
5093 ? "__OBJC,__image_info,regular
"
5094 : GetSectionName("__objc_imageinfo
", "regular,no_dead_strip
");
5096 // Generate module-level named metadata to convey this information to the
5097 // linker and code-gen.
5098 llvm::Module &Mod = CGM.getModule();
5100 // Add the ObjC ABI version to the module flags.
5101 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Version
", ObjCABI);
5102 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Image Info Version
",
5104 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Image Info Section
",
5105 llvm::MDString::get(VMContext, Section));
5107 auto Int8Ty = llvm::Type::getInt8Ty(VMContext);
5108 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
5109 // Non-GC overrides those files which specify GC.
5110 Mod.addModuleFlag(llvm::Module::Error,
5111 "Objective-
C Garbage Collection
",
5112 llvm::ConstantInt::get(Int8Ty,0));
5114 // Add the ObjC garbage collection value.
5115 Mod.addModuleFlag(llvm::Module::Error,
5116 "Objective-
C Garbage Collection
",
5117 llvm::ConstantInt::get(Int8Ty,
5118 (uint8_t)eImageInfo_GarbageCollected));
5120 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
5121 // Add the ObjC GC Only value.
5122 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C GC Only
",
5125 // Require that GC be specified and set to eImageInfo_GarbageCollected.
5126 llvm::Metadata *Ops[2] = {
5127 llvm::MDString::get(VMContext, "Objective-
C Garbage Collection
"),
5128 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
5129 Int8Ty, eImageInfo_GarbageCollected))};
5130 Mod.addModuleFlag(llvm::Module::Require, "Objective-
C GC Only
",
5131 llvm::MDNode::get(VMContext, Ops));
5135 // Indicate whether we're compiling this to run on a simulator.
5136 if (CGM.getTarget().getTriple().isSimulatorEnvironment())
5137 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Is Simulated
",
5138 eImageInfo_ImageIsSimulated);
5140 // Indicate whether we are generating class properties.
5141 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Class Properties
",
5142 eImageInfo_ClassProperties);
5145// struct objc_module {
5146// unsigned long version;
5147// unsigned long size;
5152// FIXME: Get from somewhere
5153static const int ModuleVersion = 7;
5155void CGObjCMac::EmitModuleInfo() {
5156 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
5158 ConstantInitBuilder builder(CGM);
5159 auto values = builder.beginStruct(ObjCTypes.ModuleTy);
5160 values.addInt(ObjCTypes.LongTy, ModuleVersion);
5161 values.addInt(ObjCTypes.LongTy, Size);
5162 // This used to be the filename, now it is unused. <rdr://4327263>
5163 values.add(GetClassName(StringRef("")));
5164 values.add(EmitModuleSymbols());
5165 CreateMetadataVar("OBJC_MODULES
", values,
5166 "__OBJC,__module_info,regular,no_dead_strip
",
5167 CGM.getPointerAlign(), true);
5170llvm::Constant *CGObjCMac::EmitModuleSymbols() {
5171 unsigned NumClasses = DefinedClasses.size();
5172 unsigned NumCategories = DefinedCategories.size();
5174 // Return null if no symbols were defined.
5175 if (!NumClasses && !NumCategories)
5176 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
5178 ConstantInitBuilder builder(CGM);
5179 auto values = builder.beginStruct();
5180 values.addInt(ObjCTypes.LongTy, 0);
5181 values.addNullPointer(ObjCTypes.SelectorPtrTy);
5182 values.addInt(ObjCTypes.ShortTy, NumClasses);
5183 values.addInt(ObjCTypes.ShortTy, NumCategories);
5185 // The runtime expects exactly the list of defined classes followed
5186 // by the list of defined categories, in a single array.
5187 auto array = values.beginArray(ObjCTypes.Int8PtrTy);
5188 for (unsigned i=0; i<NumClasses; i++) {
5189 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
5191 if (ObjCImplementationDecl *IMP = ID->getImplementation())
5192 // We are implementing a weak imported interface. Give it external linkage
5193 if (ID->isWeakImported() && !IMP->isWeakImported())
5194 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
5196 array.add(DefinedClasses[i]);
5198 for (unsigned i=0; i<NumCategories; i++)
5199 array.add(DefinedCategories[i]);
5201 array.finishAndAddTo(values);
5203 llvm::GlobalVariable *GV = CreateMetadataVar(
5204 "OBJC_SYMBOLS
", values, "__OBJC,__symbols,regular,no_dead_strip
",
5205 CGM.getPointerAlign(), true);
5209llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
5210 IdentifierInfo *II) {
5211 LazySymbols.insert(II);
5213 llvm::GlobalVariable *&Entry = ClassReferences[II];
5217 CreateMetadataVar("OBJC_CLASS_REFERENCES_
", GetClassName(II->getName()),
5218 "__OBJC,__cls_refs,literal_pointers,no_dead_strip
",
5219 CGM.getPointerAlign(), true);
5222 return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry,
5223 CGF.getPointerAlign());
5226llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
5227 const ObjCInterfaceDecl *ID) {
5228 // If the class has the objc_runtime_visible attribute, we need to
5229 // use the Objective-C runtime to get the class.
5230 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
5231 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
5233 IdentifierInfo *RuntimeName =
5234 &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
5235 return EmitClassRefFromId(CGF, RuntimeName);
5238llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
5239 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool
");
5240 return EmitClassRefFromId(CGF, II);
5243llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
5244 return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel));
5247ConstantAddress CGObjCMac::EmitSelectorAddr(Selector Sel) {
5248 CharUnits Align = CGM.getPointerAlign();
5250 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
5252 Entry = CreateMetadataVar(
5253 "OBJC_SELECTOR_REFERENCES_
", GetMethodVarName(Sel),
5254 "__OBJC,__message_refs,literal_pointers,no_dead_strip
", Align, true);
5255 Entry->setExternallyInitialized(true);
5258 return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align);
5261llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
5262 llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
5264 Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
5265 return getConstantGEP(VMContext, Entry, 0, 0);
5268llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
5269 return MethodDefinitions.lookup(MD);
5274llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
5275 const ObjCCommonTypesHelper &ObjCTypes) {
5276 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
5279void IvarLayoutBuilder::visitRecord(const RecordType *RT,
5281 const RecordDecl *RD = RT->getDecl();
5283 // If this is a union, remember that we had one, because it might mess
5284 // up the ordering of layout entries.
5286 IsDisordered = true;
5288 const ASTRecordLayout *recLayout = nullptr;
5289 visitAggregate(RD->field_begin(), RD->field_end(), offset,
5290 [&](const FieldDecl *field) -> CharUnits {
5292 recLayout = &CGM.getContext().getASTRecordLayout(RD);
5293 auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex());
5294 return CGM.getContext().toCharUnitsFromBits(offsetInBits);
5298template <class Iterator, class GetOffsetFn>
5299void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
5300 CharUnits aggregateOffset,
5301 const GetOffsetFn &getOffset) {
5302 for (; begin != end; ++begin) {
5303 auto field = *begin;
5305 // Skip over bitfields.
5306 if (field->isBitField()) {
5310 // Compute the offset of the field within the aggregate.
5311 CharUnits fieldOffset = aggregateOffset + getOffset(field);
5313 visitField(field, fieldOffset);
5318void IvarLayoutBuilder::visitField(const FieldDecl *field,
5319 CharUnits fieldOffset) {
5320 QualType fieldType = field->getType();
5322 // Drill down into arrays.
5323 uint64_t numElts = 1;
5324 if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) {
5326 fieldType = arrayType->getElementType();
5328 // Unlike incomplete arrays, constant arrays can be nested.
5329 while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
5330 numElts *= arrayType->getZExtSize();
5331 fieldType = arrayType->getElementType();
5334 assert(!fieldType->isArrayType() && "ivar of non-constant array
type?
");
5336 // If we ended up with a zero-sized array, we've done what we can do within
5337 // the limits of this layout encoding.
5338 if (numElts == 0) return;
5340 // Recurse if the base element type is a record type.
5341 if (auto recType = fieldType->getAs<RecordType>()) {
5342 size_t oldEnd = IvarsInfo.size();
5344 visitRecord(recType, fieldOffset);
5346 // If we have an array, replicate the first entry's layout information.
5347 auto numEltEntries = IvarsInfo.size() - oldEnd;
5348 if (numElts != 1 && numEltEntries != 0) {
5349 CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
5350 for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
5351 // Copy the last numEltEntries onto the end of the array, adjusting
5352 // each for the element size.
5353 for (size_t i = 0; i != numEltEntries; ++i) {
5354 auto firstEntry = IvarsInfo[oldEnd + i];
5355 IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
5356 firstEntry.SizeInWords));
5364 // Classify the element type.
5365 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
5367 // If it matches what we're looking for, add an entry.
5368 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
5369 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
5370 assert(CGM.getContext().getTypeSizeInChars(fieldType)
5371 == CGM.getPointerSize());
5372 IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
5379llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
5380 llvm::SmallVectorImpl<unsigned char> &buffer) {
5381 // The bitmap is a series of skip/scan instructions, aligned to word
5382 // boundaries. The skip is performed first.
5383 const unsigned char MaxNibble = 0xF;
5384 const unsigned char SkipMask = 0xF0, SkipShift = 4;
5385 const unsigned char ScanMask = 0x0F, ScanShift = 0;
5387 assert(!IvarsInfo.empty() && "generating bitmap
for no data
");
5389 // Sort the ivar info on byte position in case we encounterred a
5390 // union nested in the ivar list.
5392 // This isn't a stable sort, but our algorithm should handle it fine.
5393 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
5395 assert(llvm::is_sorted(IvarsInfo));
5397 assert(IvarsInfo.back().Offset < InstanceEnd);
5399 assert(buffer.empty());
5401 // Skip the next N words.
5402 auto skip = [&](unsigned numWords) {
5403 assert(numWords > 0);
5405 // Try to merge into the previous byte. Since scans happen second, we
5406 // can't do this if it includes a scan.
5407 if (!buffer.empty() && !(buffer.back() & ScanMask)) {
5408 unsigned lastSkip = buffer.back() >> SkipShift;
5409 if (lastSkip < MaxNibble) {
5410 unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
5411 numWords -= claimed;
5412 lastSkip += claimed;
5413 buffer.back() = (lastSkip << SkipShift);
5417 while (numWords >= MaxNibble) {
5418 buffer.push_back(MaxNibble << SkipShift);
5419 numWords -= MaxNibble;
5422 buffer.push_back(numWords << SkipShift);
5426 // Scan the next N words.
5427 auto scan = [&](unsigned numWords) {
5428 assert(numWords > 0);
5430 // Try to merge into the previous byte. Since scans happen second, we can
5431 // do this even if it includes a skip.
5432 if (!buffer.empty()) {
5433 unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
5434 if (lastScan < MaxNibble) {
5435 unsigned claimed = std::min(MaxNibble - lastScan, numWords);
5436 numWords -= claimed;
5437 lastScan += claimed;
5438 buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
5442 while (numWords >= MaxNibble) {
5443 buffer.push_back(MaxNibble << ScanShift);
5444 numWords -= MaxNibble;
5447 buffer.push_back(numWords << ScanShift);
5451 // One past the end of the last scan.
5452 unsigned endOfLastScanInWords = 0;
5453 const CharUnits WordSize = CGM.getPointerSize();
5455 // Consider all the scan requests.
5456 for (auto &request : IvarsInfo) {
5457 CharUnits beginOfScan = request.Offset - InstanceBegin;
5459 // Ignore scan requests that don't start at an even multiple of the
5460 // word size. We can't encode them.
5461 if ((beginOfScan % WordSize) != 0) continue;
5463 // Ignore scan requests that start before the instance start.
5464 // This assumes that scans never span that boundary. The boundary
5465 // isn't the true start of the ivars, because in the fragile-ARC case
5466 // it's rounded up to word alignment, but the test above should leave
5467 // us ignoring that possibility.
5468 if (beginOfScan.isNegative()) {
5469 assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
5473 unsigned beginOfScanInWords = beginOfScan / WordSize;
5474 unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
5476 // If the scan starts some number of words after the last one ended,
5478 if (beginOfScanInWords > endOfLastScanInWords) {
5479 skip(beginOfScanInWords - endOfLastScanInWords);
5481 // Otherwise, start scanning where the last left off.
5483 beginOfScanInWords = endOfLastScanInWords;
5485 // If that leaves us with nothing to scan, ignore this request.
5486 if (beginOfScanInWords >= endOfScanInWords) continue;
5489 // Scan to the end of the request.
5490 assert(beginOfScanInWords < endOfScanInWords);
5491 scan(endOfScanInWords - beginOfScanInWords);
5492 endOfLastScanInWords = endOfScanInWords;
5496 return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
5498 // For GC layouts, emit a skip to the end of the allocation so that we
5499 // have precise information about the entire thing. This isn't useful
5500 // or necessary for the ARC-style layout strings.
5501 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
5502 unsigned lastOffsetInWords =
5503 (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
5504 if (lastOffsetInWords > endOfLastScanInWords) {
5505 skip(lastOffsetInWords - endOfLastScanInWords);
5509 // Null terminate the string.
5510 buffer.push_back(0);
5512 auto *Entry = CGObjC.CreateCStringLiteral(
5513 reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName);
5514 return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
5534CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
5535 CharUnits beginOffset, CharUnits endOffset,
5536 bool ForStrongLayout, bool HasMRCWeakIvars) {
5537 // If this is MRC, and we're either building a strong layout or there
5538 // are no weak ivars, bail out early.
5539 llvm::Type *PtrTy = CGM.Int8PtrTy;
5540 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
5541 !CGM.getLangOpts().ObjCAutoRefCount &&
5542 (ForStrongLayout || !HasMRCWeakIvars))
5543 return llvm::Constant::getNullValue(PtrTy);
5545 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
5546 SmallVector<const ObjCIvarDecl*, 32> ivars;
5548 // GC layout strings include the complete object layout, possibly
5549 // inaccurately in the non-fragile ABI; the runtime knows how to fix this
5552 // ARC layout strings only include the class's ivars. In non-fragile
5553 // runtimes, that means starting at InstanceStart, rounded up to word
5554 // alignment. In fragile runtimes, there's no InstanceStart, so it means
5555 // starting at the offset of the first ivar, rounded up to word alignment.
5557 // MRC weak layout strings follow the ARC style.
5558 CharUnits baseOffset;
5559 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
5560 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
5561 IVD; IVD = IVD->getNextIvar())
5562 ivars.push_back(IVD);
5564 if (isNonFragileABI()) {
5565 baseOffset = beginOffset; // InstanceStart
5566 } else if (!ivars.empty()) {
5568 CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
5570 baseOffset = CharUnits::Zero();
5573 baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
5576 CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
5578 baseOffset = CharUnits::Zero();
5582 return llvm::Constant::getNullValue(PtrTy);
5584 IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
5586 builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
5587 [&](const ObjCIvarDecl *ivar) -> CharUnits {
5588 return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar));
5591 if (!builder.hasBitmapData())
5592 return llvm::Constant::getNullValue(PtrTy);
5594 llvm::SmallVector<unsigned char, 4> buffer;
5595 llvm::Constant *C = builder.buildBitmap(*this, buffer);
5597 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
5598 printf("\n%
s ivar layout
for class '%s':
",
5599 ForStrongLayout ? "strong
" : "weak
",
5600 OMD->getClassInterface()->getName().str().c_str());
5601 builder.dump(buffer);
5606llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
5607 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
5608 // FIXME: Avoid std::string in "Sel.
getAsString()
"
5610 Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
5611 return getConstantGEP(VMContext, Entry, 0, 0);
5614// FIXME: Merge into a single cstring creation function.
5615llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
5616 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
5619llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
5620 std::string TypeStr;
5621 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
5623 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
5625 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
5626 return getConstantGEP(VMContext, Entry, 0, 0);
5629llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
5631 std::string TypeStr =
5632 CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
5634 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
5636 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
5637 return getConstantGEP(VMContext, Entry, 0, 0);
5640// FIXME: Merge into a single cstring creation function.
5641llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
5642 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
5644 Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
5645 return getConstantGEP(VMContext, Entry, 0, 0);
5648// FIXME: Merge into a single cstring creation function.
5649// FIXME: This Decl should be more precise.
5651CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
5652 const Decl *Container) {
5653 std::string TypeStr =
5654 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
5655 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
5658void CGObjCMac::FinishModule() {
5661 // Emit the dummy bodies for any protocols which were referenced but
5663 for (auto &entry : Protocols) {
5664 llvm::GlobalVariable *global = entry.second;
5665 if (global->hasInitializer())
5668 ConstantInitBuilder builder(CGM);
5669 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
5670 values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
5671 values.add(GetClassName(entry.first->getName()));
5672 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
5673 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5674 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5675 values.finishAndSetAsInitializer(global);
5676 CGM.addCompilerUsedGlobal(global);
5679 // Add assembler directives to add lazy undefined symbol references
5680 // for classes which are referenced but not defined. This is
5681 // important for correct linker interaction.
5683 // FIXME: It would be nice if we had an LLVM construct for this.
5684 if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
5685 CGM.getTriple().isOSBinFormatMachO()) {
5686 SmallString<256> Asm;
5687 Asm += CGM.getModule().getModuleInlineAsm();
5688 if (!Asm.empty() && Asm.back() != '\n')
5691 llvm::raw_svector_ostream OS(Asm);
5692 for (const auto *Sym : DefinedSymbols)
5693 OS << "\t.objc_class_name_
" << Sym->getName() << "=0\n
"
5694 << "\t.globl .objc_class_name_
" << Sym->getName() << "\n
";
5695 for (const auto *Sym : LazySymbols)
5696 OS << "\t.lazy_reference .objc_class_name_
" << Sym->getName() << "\n
";
5697 for (const auto &Category : DefinedCategoryNames)
5698 OS << "\t.objc_category_name_
" << Category << "=0\n
"
5699 << "\t.globl .objc_category_name_
" << Category << "\n
";
5701 CGM.getModule().setModuleInlineAsm(OS.str());
5705CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
5706 : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
5707 ObjCEmptyVtableVar(nullptr) {
5713ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
5714 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr)
5716 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5717 ASTContext &Ctx = CGM.getContext();
5718 unsigned ProgramAS = CGM.getDataLayout().getProgramAddressSpace();
5720 ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
5722 LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
5723 Int8PtrTy = CGM.Int8PtrTy;
5724 Int8PtrProgramASTy = llvm::PointerType::get(CGM.Int8Ty, ProgramAS);
5725 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
5727 // arm64 targets use "int" ivar offset variables. All others,
5728 // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
5729 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
5730 IvarOffsetVarTy = IntTy;
5732 IvarOffsetVarTy = LongTy;
5735 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
5737 llvm::PointerType::getUnqual(ObjectPtrTy);
5739 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
5741 // I'm not sure I like this. The implicit coordination is a bit
5742 // gross. We should solve this in a reasonable fashion because this
5743 // is a pretty common task (match some runtime data structure with
5744 // an LLVM data structure).
5746 // FIXME: This is leaked.
5747 // FIXME: Merge with rewriter code?
5749 // struct _objc_super {
5753 RecordDecl *RD = RecordDecl::Create(
5754 Ctx, TagTypeKind::Struct, Ctx.getTranslationUnitDecl(), SourceLocation(),
5755 SourceLocation(), &Ctx.Idents.get("_objc_super
"));
5756 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5757 nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
5758 false, ICIS_NoInit));
5759 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5760 nullptr, Ctx.getObjCClassType(), nullptr,
5761 nullptr, false, ICIS_NoInit));
5762 RD->completeDefinition();
5764 SuperCTy = Ctx.getTagDeclType(RD);
5765 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
5767 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));