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())
1600 return ID->getImplementation() &&
ID->getSuperClass() &&
1601 ID->getSuperClass()->getName() ==
"NSObject";
1607 llvm::Constant *getNSConstantStringClassRef()
override;
1609 llvm::Function *ModuleInitFunction()
override;
1614 llvm::Value *Receiver,
1623 bool isCategoryImpl, llvm::Value *Receiver,
1631 {
return EmitSelector(CGF, Sel); }
1633 {
return EmitSelectorAddr(Sel); }
1639 {
return EmitSelector(CGF, Method->
getSelector()); }
1650 llvm::Constant *GetEHType(
QualType T)
override;
1652 llvm::FunctionCallee GetPropertyGetFunction()
override {
1653 return ObjCTypes.getGetPropertyFn();
1655 llvm::FunctionCallee GetPropertySetFunction()
override {
1656 return ObjCTypes.getSetPropertyFn();
1659 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
1660 bool copy)
override {
1661 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1664 llvm::FunctionCallee GetSetStructFunction()
override {
1665 return ObjCTypes.getCopyStructFn();
1668 llvm::FunctionCallee GetGetStructFunction()
override {
1669 return ObjCTypes.getCopyStructFn();
1672 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override {
1673 return ObjCTypes.getCppAtomicObjectFunction();
1676 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override {
1677 return ObjCTypes.getCppAtomicObjectFunction();
1680 llvm::FunctionCallee EnumerationMutationFunction()
override {
1681 return ObjCTypes.getEnumerationMutationFn();
1689 bool ClearInsertionPoint=
true)
override;
1691 Address AddrWeakObj)
override;
1693 llvm::Value *src,
Address edst)
override;
1695 llvm::Value *src,
Address dest,
1696 bool threadlocal =
false)
override;
1698 llvm::Value *src,
Address dest,
1699 llvm::Value *ivarOffset)
override;
1701 llvm::Value *src,
Address dest)
override;
1704 llvm::Value *size)
override;
1707 unsigned CVRQualifiers)
override;
1715struct NullReturnState {
1716 llvm::BasicBlock *NullBB =
nullptr;
1717 NullReturnState() =
default;
1729 llvm::Value *isNull = CGF.
Builder.CreateIsNull(receiver);
1730 CGF.
Builder.CreateCondBr(isNull, NullBB, callBB);
1745 if (!NullBB)
return result;
1749 llvm::BasicBlock *contBB =
nullptr;
1752 llvm::BasicBlock *callBB = CGF.
Builder.GetInsertBlock();
1767 assert(CGF.
Builder.GetInsertBlock() == NullBB);
1787 llvm::PHINode *phi = CGF.
Builder.CreatePHI(null->getType(), 2);
1789 phi->addIncoming(null, NullBB);
1798 assert(result.
isAggregate() &&
"null init of non-aggregate result?");
1807 CodeGenFunction::ComplexPairTy callResult = result.
getComplexVal();
1810 llvm::Type *scalarTy = callResult.first->getType();
1811 llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
1814 llvm::PHINode *real = CGF.
Builder.CreatePHI(scalarTy, 2);
1815 real->addIncoming(callResult.first, callBB);
1816 real->addIncoming(scalarZero, NullBB);
1817 llvm::PHINode *imag = CGF.
Builder.CreatePHI(scalarTy, 2);
1818 imag->addIncoming(callResult.second, callBB);
1819 imag->addIncoming(scalarZero, NullBB);
1830 llvm::GlobalVariable *
C,
unsigned idx0,
1832 llvm::Value *Idxs[] = {
1833 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1834 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
1836 return llvm::ConstantExpr::getGetElementPtr(
C->getValueType(),
C, Idxs);
1843 if (OID->
hasAttr<ObjCExceptionAttr>())
1850static llvm::GlobalValue::LinkageTypes
1852 if (CGM.
getTriple().isOSBinFormatMachO() &&
1853 (Section.empty() || Section.startswith(
"__DATA")))
1854 return llvm::GlobalValue::InternalLinkage;
1855 return llvm::GlobalValue::PrivateLinkage;
1859static llvm::GlobalVariable *
1862 std::string SectionName;
1863 if (CGM.
getTriple().isOSBinFormatMachO())
1864 SectionName =
"__DATA, __objc_const";
1865 auto *GV = Builder.finishAndCreateGlobal(
1868 GV->setSection(SectionName);
1884 return EmitClassRef(CGF, ID);
1889 return EmitSelector(CGF, Sel);
1892 return EmitSelectorAddr(Sel);
1899llvm::Constant *CGObjCMac::GetEHType(
QualType T) {
1913 llvm_unreachable(
"asking for catch type for ObjC type in fragile runtime");
1936CGObjCCommonMac::GenerateConstantString(
const StringLiteral *SL) {
1939 : GenerateConstantNSString(SL));
1942static llvm::StringMapEntry<llvm::GlobalVariable *> &
1945 StringRef String = Literal->getString();
1946 StringLength = String.size();
1947 return *Map.insert(std::make_pair(String,
nullptr)).first;
1950llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
1951 if (llvm::Value *
V = ConstantStringClassRef)
1952 return cast<llvm::Constant>(
V);
1956 StringClass.empty() ?
"_NSConstantStringClassReference"
1957 :
"_" + StringClass +
"ClassReference";
1959 llvm::Type *PTy = llvm::ArrayType::get(CGM.
IntTy, 0);
1961 auto V = llvm::ConstantExpr::getBitCast(GV, CGM.
IntTy->getPointerTo());
1962 ConstantStringClassRef =
V;
1966llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
1967 if (llvm::Value *
V = ConstantStringClassRef)
1968 return cast<llvm::Constant>(
V);
1972 StringClass.empty() ?
"OBJC_CLASS_$_NSConstantString"
1973 :
"OBJC_CLASS_$_" + StringClass;
1977 auto V = llvm::ConstantExpr::getBitCast(GV, CGM.
IntTy->getPointerTo());
1979 ConstantStringClassRef =
V;
1984CGObjCCommonMac::GenerateConstantNSString(
const StringLiteral *Literal) {
1985 unsigned StringLength = 0;
1986 llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
1989 if (
auto *
C = Entry.second)
1994 llvm::Constant *
Class = getNSConstantStringClassRef();
1997 if (!NSConstantStringType) {
1998 NSConstantStringType =
1999 llvm::StructType::create({
2003 },
"struct.__builtin_NSString");
2007 auto Fields = Builder.beginStruct(NSConstantStringType);
2014 llvm::ConstantDataArray::getString(VMContext, Entry.first());
2016 llvm::GlobalValue::LinkageTypes
Linkage = llvm::GlobalValue::PrivateLinkage;
2017 bool isConstant = !CGM.
getLangOpts().WritableStrings;
2019 auto *GV =
new llvm::GlobalVariable(CGM.
getModule(),
C->getType(), isConstant,
2021 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2024 GV->setAlignment(llvm::Align(1));
2028 Fields.addInt(CGM.
IntTy, StringLength);
2032 GV = Fields.finishAndCreateGlobal(
"_unnamed_nsstring_", Alignment,
2034 llvm::GlobalVariable::PrivateLinkage);
2035 const char *NSStringSection =
"__OBJC,__cstring_object,regular,no_dead_strip";
2036 const char *NSStringNonFragileABISection =
2037 "__DATA,__objc_stringobj,regular,no_dead_strip";
2040 ? NSStringNonFragileABISection
2060 bool isCategoryImpl,
2061 llvm::Value *Receiver,
2062 bool IsClassMessage,
2070 llvm::Value *ReceiverAsObject =
2071 CGF.
Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
2076 llvm::Type *ClassTyPtr = llvm::PointerType::getUnqual(ObjCTypes.ClassTy);
2078 if (IsClassMessage) {
2079 if (isCategoryImpl) {
2086 Target = EmitClassRef(CGF,
Class->getSuperClass());
2091 llvm::Constant *MetaClassPtr = EmitMetaClassRef(
Class);
2092 llvm::Value *SuperPtr =
2098 }
else if (isCategoryImpl)
2099 Target = EmitClassRef(CGF,
Class->getSuperClass());
2101 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
2108 llvm::Type *ClassTy =
2112 return EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper.
getPointer(),
2113 ObjCTypes.SuperPtrCTy,
true, CallArgs, Method, Class,
2122 llvm::Value *Receiver,
2126 return EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
2128 Method, Class, ObjCTypes);
2142 const ObjCCommonTypesHelper &ObjCTypes) {
2145 llvm::Value *SelValue = llvm::UndefValue::get(Types.ConvertType(selTy));
2149 Arg0 = CGF.
Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
2156 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
2161 "Result type mismatch!");
2163 bool ReceiverCanBeNull =
2164 canMessageReceiverBeNull(CGF, Method, IsSuper, ClassReceiver, Arg0);
2166 bool RequiresNullCheck =
false;
2167 bool RequiresSelValue =
true;
2169 llvm::FunctionCallee Fn =
nullptr;
2175 RequiresSelValue =
false;
2177 if (ReceiverCanBeNull) RequiresNullCheck =
true;
2178 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
2179 : ObjCTypes.getSendStretFn(IsSuper);
2181 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
2182 : ObjCTypes.getSendFpretFn(IsSuper);
2184 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
2185 : ObjCTypes.getSendFp2retFn(IsSuper);
2190 RequiresNullCheck =
true;
2191 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
2192 : ObjCTypes.getSendFn(IsSuper);
2196 llvm::Constant *BitcastFn = cast<llvm::Constant>(
2197 CGF.
Builder.CreateBitCast(Fn.getCallee(), MSI.MessengerType));
2202 RequiresNullCheck =
false;
2206 RequiresNullCheck =
true;
2208 NullReturnState nullReturn;
2209 if (RequiresNullCheck) {
2210 nullReturn.init(CGF, Arg0);
2214 if (RequiresSelValue) {
2215 SelValue = GetSelector(CGF, Sel);
2219 llvm::CallBase *CallSite;
2221 RValue rvalue = CGF.
EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
2226 if (Method && Method->
hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
2227 CallSite->setDoesNotReturn();
2230 return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs,
2231 RequiresNullCheck ? Method :
nullptr);
2235 bool pointee =
false) {
2248 switch (ownership) {
2255 llvm_unreachable(
"bad objc ownership");
2275 IvarInfo(
CharUnits offset, uint64_t sizeInWords)
2276 : Offset(offset), SizeInWords(sizeInWords) {}
2279 bool operator<(
const IvarInfo &other)
const {
2280 return Offset < other.Offset;
2285 class IvarLayoutBuilder {
2296 bool ForStrongLayout;
2299 bool IsDisordered =
false;
2305 CharUnits instanceEnd,
bool forStrongLayout)
2306 : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
2307 ForStrongLayout(forStrongLayout) {
2312 template <
class Iterator,
class GetOffsetFn>
2313 void visitAggregate(Iterator begin, Iterator end,
2315 const GetOffsetFn &getOffset);
2323 bool hasBitmapData()
const {
return !IvarsInfo.empty(); }
2325 llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
2329 const unsigned char *
s = buffer.data();
2330 for (
unsigned i = 0, e = buffer.size(); i < e; i++)
2332 printf(
"0x0%x%s",
s[i],
s[i] != 0 ?
", " :
"");
2334 printf(
"0x%x%s",
s[i],
s[i] != 0 ?
", " :
"");
2340llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(
CodeGenModule &CGM,
2343 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2350 builder.visitBlock(blockInfo);
2352 if (!builder.hasBitmapData())
2356 llvm::Constant *
C = builder.buildBitmap(*
this, buffer);
2357 if (CGM.
getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
2358 printf(
"\n block variable layout for block: ");
2359 builder.dump(buffer);
2365void IvarLayoutBuilder::visitBlock(
const CGBlockInfo &blockInfo) {
2378 for (
const auto &CI :
blockDecl->captures()) {
2379 const VarDecl *variable = CI.getVariable();
2391 if (fieldOffset < lastFieldOffset)
2392 IsDisordered =
true;
2393 lastFieldOffset = fieldOffset;
2397 IvarsInfo.push_back(IvarInfo(fieldOffset, 1));
2401 assert(!
type->isArrayType() &&
"array variable should not be caught");
2403 visitRecord(record, fieldOffset);
2412 IvarsInfo.push_back(IvarInfo(fieldOffset, 1));
2437void CGObjCCommonMac::UpdateRunSkipBlockVars(
bool IsByref,
2443 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
2446 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
2449 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
2452 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
2455 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2460void CGObjCCommonMac::BuildRCRecordLayout(
const llvm::StructLayout *RecLayout,
2465 bool IsUnion = (RD && RD->
isUnion());
2468 const FieldDecl *LastFieldBitfieldOrUnnamed =
nullptr;
2472 if (RecFields.empty())
2476 for (
unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2485 if (!
Field->getIdentifier() ||
Field->isBitField()) {
2486 LastFieldBitfieldOrUnnamed =
Field;
2487 LastBitfieldOrUnnamedOffset = FieldOffset;
2491 LastFieldBitfieldOrUnnamed =
nullptr;
2498 BytePos + FieldOffset, HasUnion);
2503 auto *CArray = cast<ConstantArrayType>(Array);
2504 uint64_t ElCount = CArray->getSize().getZExtValue();
2505 assert(CArray &&
"only array with known element size is supported");
2506 FQT = CArray->getElementType();
2508 auto *CArray = cast<ConstantArrayType>(Array);
2509 ElCount *= CArray->getSize().getZExtValue();
2510 FQT = CArray->getElementType();
2513 int OldIndex = RunSkipBlockVars.size() - 1;
2515 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset, HasUnion);
2520 for (
int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
2522 for (
int i = OldIndex+1; i <= FirstIndex; ++i)
2523 RunSkipBlockVars.push_back(
2524 RUN_SKIP(RunSkipBlockVars[i].opcode,
2525 RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
2526 RunSkipBlockVars[i].block_var_size));
2534 if (UnionIvarSize > MaxUnionSize) {
2535 MaxUnionSize = UnionIvarSize;
2537 MaxFieldOffset = FieldOffset;
2540 UpdateRunSkipBlockVars(
false,
2541 getBlockCaptureLifetime(FQT, ByrefLayout),
2542 BytePos + FieldOffset,
2547 if (LastFieldBitfieldOrUnnamed) {
2548 if (LastFieldBitfieldOrUnnamed->
isBitField()) {
2552 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
2553 ((BitFieldSize % ByteSizeInBits) != 0);
2555 Size += LastBitfieldOrUnnamedOffset;
2556 UpdateRunSkipBlockVars(
false,
2557 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->
getType(),
2559 BytePos + LastBitfieldOrUnnamedOffset,
2562 assert(!LastFieldBitfieldOrUnnamed->
getIdentifier() &&
"Expected unnamed");
2566 UpdateRunSkipBlockVars(
false,
2567 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->
getType(),
2569 BytePos + LastBitfieldOrUnnamedOffset,
2575 UpdateRunSkipBlockVars(
false,
2576 getBlockCaptureLifetime(MaxField->
getType(), ByrefLayout),
2577 BytePos + MaxFieldOffset,
2581void CGObjCCommonMac::BuildRCBlockVarRecordLayout(
const RecordType *RT,
2588 const llvm::StructLayout *RecLayout =
2589 CGM.
getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
2591 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
2603uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2606 if (Layout.size() <= 3) {
2607 unsigned size = Layout.size();
2608 unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
2610 enum BLOCK_LAYOUT_OPCODE opcode ;
2614 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2615 if (opcode == BLOCK_LAYOUT_STRONG)
2616 strong_word_count = (inst & 0xF)+1;
2620 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2621 if (opcode == BLOCK_LAYOUT_BYREF)
2622 byref_word_count = (inst & 0xF)+1;
2626 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2627 if (opcode == BLOCK_LAYOUT_WEAK)
2628 weak_word_count = (inst & 0xF)+1;
2635 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2636 if (opcode == BLOCK_LAYOUT_STRONG) {
2637 strong_word_count = (inst & 0xF)+1;
2639 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2640 if (opcode == BLOCK_LAYOUT_BYREF)
2641 byref_word_count = (inst & 0xF)+1;
2642 else if (opcode == BLOCK_LAYOUT_WEAK)
2643 weak_word_count = (inst & 0xF)+1;
2647 else if (opcode == BLOCK_LAYOUT_BYREF) {
2648 byref_word_count = (inst & 0xF)+1;
2650 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2651 if (opcode == BLOCK_LAYOUT_WEAK)
2652 weak_word_count = (inst & 0xF)+1;
2662 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2663 if (opcode == BLOCK_LAYOUT_STRONG)
2664 strong_word_count = (inst & 0xF)+1;
2665 else if (opcode == BLOCK_LAYOUT_BYREF)
2666 byref_word_count = (inst & 0xF)+1;
2667 else if (opcode == BLOCK_LAYOUT_WEAK)
2668 weak_word_count = (inst & 0xF)+1;
2680 if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
2684 (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
2686 if (size == count) {
2687 if (strong_word_count)
2688 Result = strong_word_count;
2690 if (byref_word_count)
2691 Result += byref_word_count;
2693 if (weak_word_count)
2694 Result += weak_word_count;
2700llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(
bool ComputeByrefLayout) {
2701 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2702 if (RunSkipBlockVars.empty())
2706 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2710 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2713 unsigned size = RunSkipBlockVars.size();
2714 for (
unsigned i = 0; i < size; i++) {
2715 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2716 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2717 CharUnits end_byte_pos = start_byte_pos;
2720 if (opcode == RunSkipBlockVars[j].opcode) {
2721 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2728 end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2731 RunSkipBlockVars[j].block_var_bytepos -
2732 RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
2733 size_in_bytes += gap;
2736 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2737 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2738 size_in_bytes -= residue_in_bytes;
2739 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2742 unsigned size_in_words = size_in_bytes.
getQuantity() / WordSizeInBytes;
2743 while (size_in_words >= 16) {
2746 unsigned char inst = (opcode << 4) | 0xf;
2747 Layout.push_back(inst);
2748 size_in_words -= 16;
2750 if (size_in_words > 0) {
2753 unsigned char inst = (opcode << 4) | (size_in_words-1);
2754 Layout.push_back(inst);
2757 unsigned char inst =
2758 (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.
getQuantity()-1);
2759 Layout.push_back(inst);
2763 while (!Layout.empty()) {
2764 unsigned char inst = Layout.back();
2765 enum BLOCK_LAYOUT_OPCODE opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2766 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2772 uint64_t Result = InlineLayoutInstruction(Layout);
2776 if (ComputeByrefLayout)
2777 printf(
"\n Inline BYREF variable layout: ");
2779 printf(
"\n Inline block variable layout: ");
2780 printf(
"0x0%" PRIx64
"", Result);
2781 if (
auto numStrong = (Result & 0xF00) >> 8)
2782 printf(
", BL_STRONG:%d", (
int) numStrong);
2783 if (
auto numByref = (Result & 0x0F0) >> 4)
2784 printf(
", BL_BYREF:%d", (
int) numByref);
2785 if (
auto numWeak = (Result & 0x00F) >> 0)
2786 printf(
", BL_WEAK:%d", (
int) numWeak);
2787 printf(
", BL_OPERATOR:0\n");
2789 return llvm::ConstantInt::get(CGM.
IntPtrTy, Result);
2792 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2793 Layout.push_back(inst);
2795 for (
unsigned i = 0, e = Layout.size(); i != e; i++)
2796 BitMap += Layout[i];
2799 if (ComputeByrefLayout)
2800 printf(
"\n Byref variable layout: ");
2802 printf(
"\n Block variable layout: ");
2803 for (
unsigned i = 0, e = BitMap.size(); i != e; i++) {
2804 unsigned char inst = BitMap[i];
2805 enum BLOCK_LAYOUT_OPCODE opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2808 case BLOCK_LAYOUT_OPERATOR:
2812 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2813 printf(
"BL_NON_OBJECT_BYTES:");
2815 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2816 printf(
"BL_NON_OBJECT_WORD:");
2818 case BLOCK_LAYOUT_STRONG:
2821 case BLOCK_LAYOUT_BYREF:
2824 case BLOCK_LAYOUT_WEAK:
2827 case BLOCK_LAYOUT_UNRETAINED:
2828 printf(
"BL_UNRETAINED:");
2833 printf(
"%d", (inst & 0xf) + delta);
2841 auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
2849 bool HasCopyDisposeHelpers) {
2851 for (
const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) {
2852 if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) {
2856 }
else if (HasCopyDisposeHelpers) {
2864 case CGObjCCommonMac::BLOCK_LAYOUT_STRONG:
2867 case CGObjCCommonMac::BLOCK_LAYOUT_BYREF:
2870 case CGObjCCommonMac::BLOCK_LAYOUT_WEAK:
2877 Str += llvm::to_string(R.block_var_bytepos.getQuantity());
2878 Str +=
"l" + llvm::to_string(R.block_var_size.getQuantity());
2883void CGObjCCommonMac::fillRunSkipBlockVars(
CodeGenModule &CGM,
2887 RunSkipBlockVars.clear();
2888 bool hasUnion =
false;
2892 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2897 const llvm::StructLayout *layout =
2907 for (
const auto &CI :
blockDecl->captures()) {
2908 const VarDecl *variable = CI.getVariable();
2919 assert(!
type->isArrayType() &&
"array variable should not be caught");
2922 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2930 UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(
type,
false),
2931 fieldOffset, fieldSize);
2938 fillRunSkipBlockVars(CGM, blockInfo);
2939 return getBitmapBlockLayout(
false);
2942std::string CGObjCCommonMac::getRCBlockLayoutStr(
CodeGenModule &CGM,
2944 fillRunSkipBlockVars(CGM, blockInfo);
2951 assert(!T->
isArrayType() &&
"__block array variable should not be caught");
2953 RunSkipBlockVars.clear();
2954 bool hasUnion =
false;
2956 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion,
true );
2957 llvm::Constant *Result = getBitmapBlockLayout(
true);
2958 if (isa<llvm::ConstantInt>(Result))
2959 Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.
Int8PtrTy);
2962 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2972 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
2973 ObjCTypes.getExternalProtocolPtrTy());
2985 GetOrEmitProtocol(PD);
2988llvm::Constant *CGObjCCommonMac::GetProtocolRef(
const ObjCProtocolDecl *PD) {
2990 return GetOrEmitProtocol(PD);
2992 return GetOrEmitProtocolRef(PD);
2995llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime(
2998 ObjCCommonTypesHelper &ObjCTypes) {
2999 llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn();
3001 llvm::Value *className = CGF.
CGM
3003 ID->getObjCRuntimeNameAsString()))
3007 CGF.
Builder.CreateBitCast(className,
3010 llvm::CallInst *call = CGF.
Builder.CreateCall(lookUpClassFn, className);
3011 call->setDoesNotThrow();
3028 llvm::GlobalVariable *Entry = Protocols[PD->
getIdentifier()];
3031 if (Entry && Entry->hasInitializer())
3043 auto methodLists = ProtocolMethodLists::get(PD);
3046 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
3047 values.add(EmitProtocolExtension(PD, methodLists));
3049 values.add(EmitProtocolList(
"OBJC_PROTOCOL_REFS_" + PD->
getName(),
3051 values.add(methodLists.emitMethodList(
this, PD,
3052 ProtocolMethodLists::RequiredInstanceMethods));
3053 values.add(methodLists.emitMethodList(
this, PD,
3054 ProtocolMethodLists::RequiredClassMethods));
3058 assert(Entry->hasPrivateLinkage());
3059 values.finishAndSetAsInitializer(Entry);
3061 Entry = values.finishAndCreateGlobal(
"OBJC_PROTOCOL_" + PD->
getName(),
3064 llvm::GlobalValue::PrivateLinkage);
3065 Entry->setSection(
"__OBJC,__protocol,regular,no_dead_strip");
3074llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD) {
3075 llvm::GlobalVariable *&Entry = Protocols[PD->
getIdentifier()];
3081 Entry =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ProtocolTy,
3082 false, llvm::GlobalValue::PrivateLinkage,
3083 nullptr,
"OBJC_PROTOCOL_" + PD->
getName());
3084 Entry->setSection(
"__OBJC,__protocol,regular,no_dead_strip");
3086 Entry->setAlignment(llvm::Align(4));
3104 const ProtocolMethodLists &methodLists) {
3105 auto optInstanceMethods =
3106 methodLists.emitMethodList(
this, PD,
3107 ProtocolMethodLists::OptionalInstanceMethods);
3108 auto optClassMethods =
3109 methodLists.emitMethodList(
this, PD,
3110 ProtocolMethodLists::OptionalClassMethods);
3112 auto extendedMethodTypes =
3113 EmitProtocolMethodTypes(
"OBJC_PROTOCOL_METHOD_TYPES_" + PD->
getName(),
3114 methodLists.emitExtendedTypesArray(
this),
3117 auto instanceProperties =
3118 EmitPropertyList(
"OBJC_$_PROP_PROTO_LIST_" + PD->
getName(),
nullptr, PD,
3120 auto classProperties =
3121 EmitPropertyList(
"OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->
getName(),
nullptr,
3122 PD, ObjCTypes,
true);
3125 if (optInstanceMethods->isNullValue() &&
3126 optClassMethods->isNullValue() &&
3127 extendedMethodTypes->isNullValue() &&
3128 instanceProperties->isNullValue() &&
3129 classProperties->isNullValue()) {
3130 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
3134 CGM.
getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
3137 auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
3138 values.addInt(ObjCTypes.IntTy, size);
3139 values.add(optInstanceMethods);
3140 values.add(optClassMethods);
3141 values.add(instanceProperties);
3142 values.add(extendedMethodTypes);
3143 values.add(classProperties);
3146 return CreateMetadataVar(
"_OBJC_PROTOCOLEXT_" + PD->
getName(), values,
3158CGObjCMac::EmitProtocolList(Twine name,
3162 auto PDs = GetRuntimeProtocolList(begin, end);
3164 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
3167 auto values = builder.beginStruct();
3170 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
3173 auto countSlot = values.addPlaceholder();
3175 auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
3176 for (
const auto *Proto : PDs)
3177 refsArray.add(GetProtocolRef(Proto));
3179 auto count = refsArray.size();
3182 refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
3184 refsArray.finishAndAddTo(values);
3185 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
3188 if (CGM.
getTriple().isOSBinFormatMachO())
3189 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3191 llvm::GlobalVariable *GV =
3192 CreateMetadataVar(name, values, section, CGM.
getPointerAlign(),
false);
3193 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
3200 bool IsClassProperty) {
3202 if (IsClassProperty != PD->isClassProperty())
3206 Properties.push_back(PD);
3225llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
3226 const Decl *Container,
3228 const ObjCCommonTypesHelper &ObjCTypes,
3229 bool IsClassProperty) {
3230 if (IsClassProperty) {
3234 if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
3235 (Triple.isiOS() && Triple.isOSVersionLT(9)))
3236 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3244 for (
auto *PD : ClassExt->properties()) {
3245 if (IsClassProperty != PD->isClassProperty())
3247 if (PD->isDirectProperty())
3250 Properties.push_back(PD);
3254 if (IsClassProperty != PD->isClassProperty())
3260 if (PD->isDirectProperty())
3262 Properties.push_back(PD);
3266 for (
const auto *
P : OID->all_referenced_protocols())
3270 for (
const auto *
P : CD->protocols())
3275 if (Properties.empty())
3276 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3278 unsigned propertySize =
3282 auto values = builder.beginStruct();
3283 values.addInt(ObjCTypes.IntTy, propertySize);
3284 values.addInt(ObjCTypes.IntTy, Properties.size());
3285 auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
3286 for (
auto PD : Properties) {
3287 auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
3289 property.add(GetPropertyTypeString(PD, Container));
3290 property.finishAndAddTo(propertiesArray);
3292 propertiesArray.finishAndAddTo(values);
3295 if (CGM.
getTriple().isOSBinFormatMachO())
3296 Section = (ObjCABI == 2) ?
"__DATA, __objc_const"
3297 :
"__OBJC,__property,regular,no_dead_strip";
3299 llvm::GlobalVariable *GV =
3300 CreateMetadataVar(Name, values, Section, CGM.
getPointerAlign(),
true);
3301 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
3305CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
3307 const ObjCCommonTypesHelper &ObjCTypes) {
3309 if (MethodTypes.empty())
3310 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
3312 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3313 MethodTypes.size());
3314 llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
3317 if (CGM.
getTriple().isOSBinFormatMachO() && ObjCABI == 2)
3318 Section =
"__DATA, __objc_const";
3320 llvm::GlobalVariable *GV =
3322 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
3349 llvm::raw_svector_ostream(ExtName) << Interface->
getName() <<
'_'
3353 auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
3361 for (
const auto *MD : OCD->
methods()) {
3362 if (!MD->isDirectMethod())
3363 Methods[
unsigned(MD->isClassMethod())].push_back(MD);
3366 Values.add(GetClassName(OCD->
getName()));
3370 Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
3371 Methods[InstanceMethods]));
3372 Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
3373 Methods[ClassMethods]));
3376 EmitProtocolList(
"OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
3379 Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
3381 Values.addInt(ObjCTypes.IntTy, Size);
3385 Values.add(EmitPropertyList(
"_OBJC_$_PROP_LIST_" + ExtName.str(),
3387 Values.add(EmitPropertyList(
"_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
3390 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3391 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3394 llvm::GlobalVariable *GV =
3395 CreateMetadataVar(
"OBJC_CATEGORY_" + ExtName.str(), Values,
3396 "__OBJC,__category,regular,no_dead_strip",
3398 DefinedCategories.push_back(GV);
3399 DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
3401 MethodDefinitions.clear();
3461 for (
auto *field : recType->getDecl()->fields()) {
3479 ID->getClassInterface()->all_declared_ivar_begin();
3480 ivar; ivar = ivar->getNextIvar()) {
3510 DefinedSymbols.insert(RuntimeName);
3512 std::string ClassName =
ID->getNameAsString();
3516 llvm::Constant *Protocols =
3517 EmitProtocolList(
"OBJC_CLASS_PROTOCOLS_" +
ID->getName(),
3521 if (
ID->hasNonZeroConstructors() ||
ID->hasDestructors())
3524 bool hasMRCWeak =
false;
3544 for (
const auto *MD :
ID->methods()) {
3545 if (!MD->isDirectMethod())
3546 Methods[
unsigned(MD->isClassMethod())].push_back(MD);
3549 for (
const auto *PID :
ID->property_impls()) {
3551 if (PID->getPropertyDecl()->isDirectProperty())
3554 if (GetMethodDefinition(MD))
3555 Methods[InstanceMethods].push_back(MD);
3557 if (GetMethodDefinition(MD))
3558 Methods[InstanceMethods].push_back(MD);
3563 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3564 values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
3567 LazySymbols.insert(Super->getIdentifier());
3569 values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
3570 ObjCTypes.ClassPtrTy);
3572 values.addNullPointer(ObjCTypes.ClassPtrTy);
3574 values.add(GetClassName(
ID->getObjCRuntimeNameAsString()));
3576 values.addInt(ObjCTypes.LongTy, 0);
3577 values.addInt(ObjCTypes.LongTy, Flags);
3578 values.addInt(ObjCTypes.LongTy,
Size.getQuantity());
3579 values.add(EmitIvarList(ID,
false));
3580 values.add(emitMethodList(
ID->getName(), MethodListType::InstanceMethods,
3581 Methods[InstanceMethods]));
3583 values.addNullPointer(ObjCTypes.CachePtrTy);
3584 values.add(Protocols);
3586 values.add(EmitClassExtension(ID, Size, hasMRCWeak,
3589 std::string Name(
"OBJC_CLASS_");
3591 const char *Section =
"__OBJC,__class,regular,no_dead_strip";
3593 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3595 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3596 "Forward metaclass reference has incorrect type.");
3597 values.finishAndSetAsInitializer(GV);
3598 GV->setSection(Section);
3602 GV = CreateMetadataVar(Name, values, Section, CGM.
getPointerAlign(),
true);
3603 DefinedClasses.push_back(GV);
3604 ImplementedClasses.push_back(Interface);
3606 MethodDefinitions.clear();
3610 llvm::Constant *Protocols,
3619 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3625 ObjCTypes.ClassPtrTy);
3630 values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()),
3631 ObjCTypes.ClassPtrTy);
3633 values.addNullPointer(ObjCTypes.ClassPtrTy);
3635 values.
add(GetClassName(
ID->getObjCRuntimeNameAsString()));
3637 values.addInt(ObjCTypes.LongTy, 0);
3638 values.addInt(ObjCTypes.LongTy, Flags);
3639 values.addInt(ObjCTypes.LongTy, Size);
3640 values.add(EmitIvarList(ID,
true));
3641 values.add(emitMethodList(
ID->getName(), MethodListType::ClassMethods,
3644 values.addNullPointer(ObjCTypes.CachePtrTy);
3645 values.add(Protocols);
3647 values.addNullPointer(ObjCTypes.Int8PtrTy);
3652 std::string Name(
"OBJC_METACLASS_");
3653 Name +=
ID->getName();
3656 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3658 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3659 "Forward metaclass reference has incorrect type.");
3660 values.finishAndSetAsInitializer(GV);
3664 llvm::GlobalValue::PrivateLinkage);
3666 GV->setSection(
"__OBJC,__meta_class,regular,no_dead_strip");
3673 std::string Name =
"OBJC_METACLASS_" +
ID->getNameAsString();
3683 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3685 GV =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ClassTy,
false,
3686 llvm::GlobalValue::PrivateLinkage,
nullptr,
3689 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3690 "Forward metaclass reference has incorrect type.");
3695 std::string Name =
"OBJC_CLASS_" +
ID->getNameAsString();
3696 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3699 GV =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ClassTy,
false,
3700 llvm::GlobalValue::PrivateLinkage,
nullptr,
3703 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3704 "Forward class metadata reference has incorrect type.");
3724 llvm::Constant *layout;
3726 layout = llvm::ConstantPointerNull::get(CGM.
Int8PtrTy);
3733 llvm::Constant *propertyList =
3734 EmitPropertyList((isMetaclass ? Twine(
"_OBJC_$_CLASS_PROP_LIST_")
3735 : Twine(
"_OBJC_$_PROP_LIST_"))
3737 ID,
ID->getClassInterface(), ObjCTypes, isMetaclass);
3740 if (layout->isNullValue() && propertyList->isNullValue()) {
3741 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
3745 CGM.
getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
3748 auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
3749 values.addInt(ObjCTypes.IntTy, size);
3751 values.add(propertyList);
3753 return CreateMetadataVar(
"OBJC_CLASSEXT_" +
ID->getName(), values,
3754 "__OBJC,__class_ext,regular,no_dead_strip",
3778 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
3783 auto ivarList = builder.beginStruct();
3784 auto countSlot = ivarList.addPlaceholder();
3785 auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
3790 if (!IVD->getDeclName())
3793 auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
3794 ivar.add(GetMethodVarName(IVD->getIdentifier()));
3795 ivar.add(GetMethodVarType(IVD));
3796 ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
3797 ivar.finishAndAddTo(ivars);
3801 auto count = ivars.size();
3805 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
3808 ivars.finishAndAddTo(ivarList);
3809 ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
3811 llvm::GlobalVariable *GV;
3812 GV = CreateMetadataVar(
"OBJC_INSTANCE_VARIABLES_" +
ID->getName(), ivarList,
3813 "__OBJC,__instance_vars,regular,no_dead_strip",
3815 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
3826 auto description = builder.
beginStruct(ObjCTypes.MethodDescriptionTy);
3827 description.addBitCast(GetMethodVarName(MD->
getSelector()),
3828 ObjCTypes.SelectorPtrTy);
3829 description.add(GetMethodVarType(MD));
3830 description.finishAndAddTo(builder);
3842 llvm::Function *fn = GetMethodDefinition(MD);
3843 assert(fn &&
"no definition registered for method");
3845 auto method = builder.
beginStruct(ObjCTypes.MethodTy);
3846 method.addBitCast(GetMethodVarName(MD->
getSelector()),
3847 ObjCTypes.SelectorPtrTy);
3848 method.add(GetMethodVarType(MD));
3849 method.addBitCast(fn, ObjCTypes.Int8PtrTy);
3850 method.finishAndAddTo(builder);
3866llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
3870 bool forProtocol =
false;
3872 case MethodListType::CategoryInstanceMethods:
3873 prefix =
"OBJC_CATEGORY_INSTANCE_METHODS_";
3874 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3875 forProtocol =
false;
3877 case MethodListType::CategoryClassMethods:
3878 prefix =
"OBJC_CATEGORY_CLASS_METHODS_";
3879 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3880 forProtocol =
false;
3882 case MethodListType::InstanceMethods:
3883 prefix =
"OBJC_INSTANCE_METHODS_";
3884 section =
"__OBJC,__inst_meth,regular,no_dead_strip";
3885 forProtocol =
false;
3887 case MethodListType::ClassMethods:
3888 prefix =
"OBJC_CLASS_METHODS_";
3889 section =
"__OBJC,__cls_meth,regular,no_dead_strip";
3890 forProtocol =
false;
3892 case MethodListType::ProtocolInstanceMethods:
3893 prefix =
"OBJC_PROTOCOL_INSTANCE_METHODS_";
3894 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3897 case MethodListType::ProtocolClassMethods:
3898 prefix =
"OBJC_PROTOCOL_CLASS_METHODS_";
3899 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3902 case MethodListType::OptionalProtocolInstanceMethods:
3903 prefix =
"OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
3904 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3907 case MethodListType::OptionalProtocolClassMethods:
3908 prefix =
"OBJC_PROTOCOL_CLASS_METHODS_OPT_";
3909 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3915 if (methods.empty())
3916 return llvm::Constant::getNullValue(forProtocol
3917 ? ObjCTypes.MethodDescriptionListPtrTy
3918 : ObjCTypes.MethodListPtrTy);
3925 values.addInt(ObjCTypes.IntTy, methods.size());
3926 auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
3927 for (
auto MD : methods) {
3928 emitMethodDescriptionConstant(methodArray, MD);
3930 methodArray.finishAndAddTo(values);
3932 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3934 return llvm::ConstantExpr::getBitCast(GV,
3935 ObjCTypes.MethodDescriptionListPtrTy);
3941 values.addNullPointer(ObjCTypes.Int8PtrTy);
3942 values.addInt(ObjCTypes.IntTy, methods.size());
3943 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
3944 for (
auto MD : methods) {
3946 emitMethodConstant(methodArray, MD);
3948 methodArray.finishAndAddTo(values);
3950 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3952 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
3955llvm::Function *CGObjCCommonMac::GenerateMethod(
const ObjCMethodDecl *OMD,
3957 llvm::Function *Method;
3960 Method = GenerateDirectMethod(OMD, CD);
3962 auto Name = getSymbolNameForMethod(OMD);
3965 llvm::FunctionType *MethodTy =
3966 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
3968 llvm::Function::Create(MethodTy, llvm::GlobalValue::InternalLinkage,
3972 MethodDefinitions.insert(std::make_pair(OMD, Method));
3981 auto I = DirectMethodDefinitions.find(COMD);
3982 llvm::Function *OldFn =
nullptr, *Fn =
nullptr;
3984 if (I != DirectMethodDefinitions.end()) {
4000 llvm::FunctionType *MethodTy =
4001 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
4004 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
4006 Fn->takeName(OldFn);
4007 OldFn->replaceAllUsesWith(
4008 llvm::ConstantExpr::getBitCast(Fn, OldFn->getType()));
4009 OldFn->eraseFromParent();
4014 auto Name = getSymbolNameForMethod(OMD,
false);
4016 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
4018 DirectMethodDefinitions.insert(std::make_pair(COMD, Fn));
4024void CGObjCCommonMac::GenerateDirectMethodPrologue(
4028 bool ReceiverCanBeNull =
true;
4030 auto selfValue = Builder.CreateLoad(selfAddr);
4048 "GenerateDirectMethod() should be called with the Class Interface");
4061 result = GeneratePossiblySpecializedMessageSend(
4069 ReceiverCanBeNull = isWeakLinkedClass(OID);
4072 if (ReceiverCanBeNull) {
4073 llvm::BasicBlock *SelfIsNilBlock =
4075 llvm::BasicBlock *ContBlock =
4079 auto selfTy = cast<llvm::PointerType>(selfValue->getType());
4080 auto Zero = llvm::ConstantPointerNull::get(selfTy);
4083 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero), SelfIsNilBlock,
4084 ContBlock, MDHelper.createBranchWeights(1, 1 << 20));
4090 Builder.SetInsertPoint(SelfIsNilBlock);
4091 if (!retTy->isVoidType()) {
4099 Builder.SetInsertPoint(ContBlock);
4107 Builder.CreateStore(GetSelector(CGF, OMD),
4112llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
4117 llvm::GlobalValue::LinkageTypes
LT =
4119 llvm::GlobalVariable *GV =
4120 Init.finishAndCreateGlobal(Name, Align,
false,
LT);
4121 if (!Section.empty())
4122 GV->setSection(Section);
4128llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
4129 llvm::Constant *Init,
4133 llvm::Type *Ty = Init->getType();
4134 llvm::GlobalValue::LinkageTypes
LT =
4136 llvm::GlobalVariable *GV =
4137 new llvm::GlobalVariable(CGM.
getModule(), Ty,
false,
LT, Init, Name);
4138 if (!Section.empty())
4139 GV->setSection(Section);
4146llvm::GlobalVariable *
4147CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType
Type,
4148 bool ForceNonFragileABI,
4149 bool NullTerminate) {
4152 case ObjCLabelType::ClassName:
Label =
"OBJC_CLASS_NAME_";
break;
4153 case ObjCLabelType::MethodVarName:
Label =
"OBJC_METH_VAR_NAME_";
break;
4154 case ObjCLabelType::MethodVarType:
Label =
"OBJC_METH_VAR_TYPE_";
break;
4155 case ObjCLabelType::PropertyName:
Label =
"OBJC_PROP_NAME_ATTR_";
break;
4158 bool NonFragile = ForceNonFragileABI || isNonFragileABI();
4162 case ObjCLabelType::ClassName:
4163 Section = NonFragile ?
"__TEXT,__objc_classname,cstring_literals"
4164 :
"__TEXT,__cstring,cstring_literals";
4166 case ObjCLabelType::MethodVarName:
4167 Section = NonFragile ?
"__TEXT,__objc_methname,cstring_literals"
4168 :
"__TEXT,__cstring,cstring_literals";
4170 case ObjCLabelType::MethodVarType:
4171 Section = NonFragile ?
"__TEXT,__objc_methtype,cstring_literals"
4172 :
"__TEXT,__cstring,cstring_literals";
4174 case ObjCLabelType::PropertyName:
4175 Section = NonFragile ?
"__TEXT,__objc_methname,cstring_literals"
4176 :
"__TEXT,__cstring,cstring_literals";
4180 llvm::Constant *
Value =
4181 llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
4182 llvm::GlobalVariable *GV =
4185 llvm::GlobalValue::PrivateLinkage,
Value,
Label);
4186 if (CGM.
getTriple().isOSBinFormatMachO())
4187 GV->setSection(Section);
4188 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4195llvm::Function *CGObjCMac::ModuleInitFunction() {
4201llvm::FunctionCallee CGObjCMac::GetPropertyGetFunction() {
4202 return ObjCTypes.getGetPropertyFn();
4205llvm::FunctionCallee CGObjCMac::GetPropertySetFunction() {
4206 return ObjCTypes.getSetPropertyFn();
4209llvm::FunctionCallee CGObjCMac::GetOptimizedPropertySetFunction(
bool atomic,
4211 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
4214llvm::FunctionCallee CGObjCMac::GetGetStructFunction() {
4215 return ObjCTypes.getCopyStructFn();
4218llvm::FunctionCallee CGObjCMac::GetSetStructFunction() {
4219 return ObjCTypes.getCopyStructFn();
4222llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectGetFunction() {
4223 return ObjCTypes.getCppAtomicObjectFunction();
4226llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectSetFunction() {
4227 return ObjCTypes.getCppAtomicObjectFunction();
4230llvm::FunctionCallee CGObjCMac::EnumerationMutationFunction() {
4231 return ObjCTypes.getEnumerationMutationFn();
4235 return EmitTryOrSynchronizedStmt(CGF, S);
4240 return EmitTryOrSynchronizedStmt(CGF, S);
4249 ObjCTypesHelper &ObjCTypes;
4250 PerformFragileFinally(
const Stmt *S,
4254 ObjCTypesHelper *ObjCTypes)
4255 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
4256 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
4261 llvm::BasicBlock *FinallyCallExit =
4263 llvm::BasicBlock *FinallyNoCallExit =
4266 FinallyCallExit, FinallyNoCallExit);
4274 if (isa<ObjCAtTryStmt>(S)) {
4276 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
4278 if (flags.isForEHCleanup())
return;
4282 llvm::Value *CurCleanupDest =
4285 CGF.
EmitStmt(FinallyStmt->getFinallyBody());
4304 class FragileHazards {
4309 llvm::InlineAsm *ReadHazard;
4310 llvm::InlineAsm *WriteHazard;
4312 llvm::FunctionType *GetAsmFnType();
4314 void collectLocals();
4320 void emitWriteHazard();
4321 void emitHazardsInNewBlocks();
4333 if (Locals.empty())
return;
4336 for (llvm::Function::iterator
4337 I = CGF.
CurFn->begin(), E = CGF.
CurFn->end(); I != E; ++I)
4338 BlocksBeforeTry.insert(&*I);
4340 llvm::FunctionType *AsmFnTy = GetAsmFnType();
4348 std::string Constraint;
4349 for (
unsigned I = 0, E = Locals.size(); I != E; ++I) {
4350 if (I) Constraint +=
',';
4354 ReadHazard = llvm::InlineAsm::get(AsmFnTy,
"", Constraint,
true,
false);
4362 std::string Constraint;
4363 for (
unsigned I = 0, E = Locals.size(); I != E; ++I) {
4364 if (I) Constraint +=
',';
4365 Constraint +=
"=*m";
4368 WriteHazard = llvm::InlineAsm::get(AsmFnTy,
"", Constraint,
true,
false);
4373void FragileHazards::emitWriteHazard() {
4374 if (Locals.empty())
return;
4377 for (
auto Pair : llvm::enumerate(Locals))
4378 Call->addParamAttr(Pair.index(), llvm::Attribute::get(
4380 cast<llvm::AllocaInst>(Pair.value())->getAllocatedType()));
4383void FragileHazards::emitReadHazard(
CGBuilderTy &Builder) {
4384 assert(!Locals.empty());
4385 llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
4386 call->setDoesNotThrow();
4388 for (
auto Pair : llvm::enumerate(Locals))
4389 call->addParamAttr(Pair.index(), llvm::Attribute::get(
4390 Builder.getContext(), llvm::Attribute::ElementType,
4391 cast<llvm::AllocaInst>(Pair.value())->getAllocatedType()));
4396void FragileHazards::emitHazardsInNewBlocks() {
4397 if (Locals.empty())
return;
4402 for (llvm::Function::iterator
4403 FI = CGF.
CurFn->begin(), FE = CGF.
CurFn->end(); FI != FE; ++FI) {
4404 llvm::BasicBlock &BB = *FI;
4405 if (BlocksBeforeTry.count(&BB))
continue;
4408 for (llvm::BasicBlock::iterator
4409 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
4410 llvm::Instruction &I = *BI;
4414 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I))
4416 if (isa<llvm::IntrinsicInst>(I))
4421 if (cast<llvm::CallBase>(I).doesNotThrow())
4429 Builder.SetInsertPoint(&BB, BI);
4430 emitReadHazard(Builder);
4436 if (
V.isValid()) S.insert(
V.getPointer());
4439void FragileHazards::collectLocals() {
4447 llvm::BasicBlock &Entry = CGF.
CurFn->getEntryBlock();
4448 for (llvm::BasicBlock::iterator
4449 I = Entry.begin(), E = Entry.end(); I != E; ++I)
4450 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
4451 Locals.push_back(&*I);
4454llvm::FunctionType *FragileHazards::GetAsmFnType() {
4456 for (
unsigned i = 0, e = Locals.size(); i != e; ++i)
4457 tys[i] = Locals[i]->getType();
4458 return llvm::FunctionType::get(CGF.
VoidTy, tys,
false);
4571 bool isTry = isa<ObjCAtTryStmt>(S);
4575 CodeGenFunction::JumpDest FinallyEnd =
4580 CodeGenFunction::JumpDest FinallyRethrow =
4590 llvm::Value *SyncArg =
4591 CGF.
EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
4592 SyncArg = CGF.
Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
4604 "exceptiondata.ptr");
4610 FragileHazards Hazards(CGF);
4639 ExceptionData.getPointer());
4642 llvm::Constant *
Zero = llvm::ConstantInt::get(CGF.
Builder.getInt32Ty(), 0);
4645 ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes,
4648 ObjCTypes.getSetJmpFn(), SetJmpBuffer,
"setjmp_result");
4649 SetJmpResult->setCanReturnTwice();
4655 llvm::Value *DidCatch =
4656 CGF.
Builder.CreateIsNotNull(SetJmpResult,
"did_catch_exception");
4657 CGF.
Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
4662 CGF.
EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
4663 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
4665 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.
Builder.saveAndClearIP();
4671 Hazards.emitWriteHazard();
4675 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
4684 llvm::CallInst *Caught =
4686 ExceptionData.getPointer(),
"caught");
4696 llvm::BasicBlock *CatchBlock =
nullptr;
4697 llvm::BasicBlock *CatchHandler =
nullptr;
4703 "propagating_exception");
4709 ExceptionData.getPointer());
4711 llvm::CallInst *SetJmpResult =
4713 SetJmpBuffer,
"setjmp.result");
4714 SetJmpResult->setCanReturnTwice();
4716 llvm::Value *Threw =
4717 CGF.
Builder.CreateIsNotNull(SetJmpResult,
"did_catch_exception");
4721 CGF.
Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
4731 bool AllMatched =
false;
4733 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
4752 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4759 EmitInitOfCatchParam(CGF, Caught, CatchParam);
4762 CGF.
EmitStmt(CatchStmt->getCatchBody());
4765 CatchVarCleanups.ForceCleanup();
4771 assert(OPT &&
"Unexpected non-object pointer type in @catch");
4776 assert(IDecl &&
"Catch parameter must have Objective-C type!");
4779 llvm::Value *
Class = EmitClassRef(CGF, IDecl);
4781 llvm::Value *matchArgs[] = {
Class, Caught };
4782 llvm::CallInst *Match =
4784 matchArgs,
"match");
4789 CGF.
Builder.CreateCondBr(CGF.
Builder.CreateIsNotNull(Match,
"matched"),
4790 MatchedBlock, NextCatchBlock);
4797 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4804 CGF.
Builder.CreateBitCast(Caught,
4806 EmitInitOfCatchParam(CGF, Tmp, CatchParam);
4808 CGF.
EmitStmt(CatchStmt->getCatchBody());
4811 CatchVarCleanups.ForceCleanup();
4822 if (Caught->use_empty())
4823 Caught->eraseFromParent();
4839 assert(PropagatingExnVar.
isValid());
4840 llvm::CallInst *NewCaught =
4842 ExceptionData.getPointer(),
"caught");
4852 Hazards.emitHazardsInNewBlocks();
4855 CGF.
Builder.restoreIP(TryFallthroughIP);
4859 CGF.
EmitBlock(FinallyEnd.getBlock(),
true);
4862 CGBuilderTy::InsertPoint SavedIP = CGF.
Builder.saveAndClearIP();
4863 CGF.
EmitBlock(FinallyRethrow.getBlock(),
true);
4866 llvm::Value *PropagatingExn;
4867 if (PropagatingExnVar.
isValid()) {
4872 llvm::CallInst *Caught =
4874 ExceptionData.getPointer());
4875 PropagatingExn = Caught;
4880 CGF.
Builder.CreateUnreachable();
4883 CGF.
Builder.restoreIP(SavedIP);
4888 bool ClearInsertionPoint) {
4889 llvm::Value *ExceptionAsObject;
4891 if (
const Expr *ThrowExpr = S.getThrowExpr()) {
4894 CGF.
Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
4897 "Unexpected rethrow outside @catch block.");
4901 CGF.
EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
4902 ->setDoesNotReturn();
4903 CGF.
Builder.CreateUnreachable();
4906 if (ClearInsertionPoint)
4907 CGF.
Builder.ClearInsertionPoint();
4916 llvm::Value *AddrWeakObjVal = CGF.
Builder.CreateBitCast(
4917 AddrWeakObj.
getPointer(), ObjCTypes.PtrObjectPtrTy);
4918 llvm::Value *read_weak =
4920 AddrWeakObjVal,
"weakread");
4921 read_weak = CGF.
Builder.CreateBitCast(read_weak, DestTy);
4929 llvm::Value *src,
Address dst) {
4930 llvm::Type * SrcTy = src->getType();
4931 if (!isa<llvm::PointerType>(SrcTy)) {
4933 assert(Size <= 8 && "does not support size > 8
");
4934 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4935 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4936 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4938 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4939 llvm::Value *dstVal =
4940 CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy);
4941 llvm::Value *args[] = { src, dstVal };
4942 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
4943 args, "weakassign
");
4949void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
4950 llvm::Value *src, Address dst,
4952 llvm::Type * SrcTy = src->getType();
4953 if (!isa<llvm::PointerType>(SrcTy)) {
4954 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4955 assert(Size <= 8 && "does
not support size > 8
");
4956 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4957 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4958 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4960 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4961 llvm::Value *dstVal =
4962 CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy);
4963 llvm::Value *args[] = {src, dstVal};
4965 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
4966 args, "globalassign
");
4968 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
4969 args, "threadlocalassign
");
4975void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
4976 llvm::Value *src, Address dst,
4977 llvm::Value *ivarOffset) {
4978 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is
NULL");
4979 llvm::Type * SrcTy = src->getType();
4980 if (!isa<llvm::PointerType>(SrcTy)) {
4981 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4982 assert(Size <= 8 && "does
not support size > 8
");
4983 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4984 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4985 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4987 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4988 llvm::Value *dstVal =
4989 CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy);
4990 llvm::Value *args[] = {src, dstVal, ivarOffset};
4991 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
4997void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
4998 llvm::Value *src, Address dst) {
4999 llvm::Type * SrcTy = src->getType();
5000 if (!isa<llvm::PointerType>(SrcTy)) {
5001 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
5002 assert(Size <= 8 && "does
not support size > 8
");
5003 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
5004 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
5005 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5007 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5008 llvm::Value *dstVal =
5009 CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy);
5010 llvm::Value *args[] = {src, dstVal};
5011 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
5012 args, "strongassign
");
5015void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
5016 Address DestPtr, Address SrcPtr,
5017 llvm::Value *size) {
5018 llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size };
5019 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
5024LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
5026 llvm::Value *BaseValue,
5027 const ObjCIvarDecl *Ivar,
5028 unsigned CVRQualifiers) {
5029 const ObjCInterfaceDecl *ID =
5030 ObjectTy->castAs<ObjCObjectType>()->getInterface();
5031 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5032 EmitIvarOffset(CGF, ID, Ivar));
5035llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
5036 const ObjCInterfaceDecl *Interface,
5037 const ObjCIvarDecl *Ivar) {
5038 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
5039 return llvm::ConstantInt::get(
5040 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
5044/* *** Private Interface *** */
5046std::string CGObjCCommonMac::GetSectionName(StringRef Section,
5047 StringRef MachOAttributes) {
5048 switch (CGM.getTriple().getObjectFormat()) {
5049 case llvm::Triple::UnknownObjectFormat:
5050 llvm_unreachable("unexpected
object file format
");
5051 case llvm::Triple::MachO: {
5052 if (MachOAttributes.empty())
5053 return ("__DATA,
" + Section).str();
5054 return ("__DATA,
" + Section + ",
" + MachOAttributes).str();
5056 case llvm::Triple::ELF:
5057 assert(Section.substr(0, 2) == "__
" &&
5058 "expected the name to begin with __
");
5059 return Section.substr(2).str();
5060 case llvm::Triple::COFF:
5061 assert(Section.substr(0, 2) == "__
" &&
5062 "expected the name to begin with __
");
5063 return (".
" + Section.substr(2) + "$B
").str();
5064 case llvm::Triple::Wasm:
5065 case llvm::Triple::GOFF:
5066 case llvm::Triple::SPIRV:
5067 case llvm::Triple::XCOFF:
5068 case llvm::Triple::DXContainer:
5069 llvm::report_fatal_error(
5070 "Objective-
C support is unimplemented
for object file format
");
5073 llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType
enum");
5084enum ImageInfoFlags {
5085 eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
5086 eImageInfo_GarbageCollected = (1 << 1),
5087 eImageInfo_GCOnly = (1 << 2),
5088 eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
5090 // A flag indicating that the module has no instances of a @synthesize of a
5091 // superclass variable. This flag used to be consumed by the runtime to work
5092 // around miscompile by gcc.
5093 eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang.
5094 eImageInfo_ImageIsSimulated = (1 << 5),
5095 eImageInfo_ClassProperties = (1 << 6)
5098void CGObjCCommonMac::EmitImageInfo() {
5099 unsigned version = 0; // Version is unused?
5100 std::string Section =
5102 ? "__OBJC,__image_info,regular
"
5103 : GetSectionName("__objc_imageinfo
", "regular,no_dead_strip
");
5105 // Generate module-level named metadata to convey this information to the
5106 // linker and code-gen.
5107 llvm::Module &Mod = CGM.getModule();
5109 // Add the ObjC ABI version to the module flags.
5110 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Version
", ObjCABI);
5111 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Image Info Version
",
5113 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Image Info Section
",
5114 llvm::MDString::get(VMContext, Section));
5116 auto Int8Ty = llvm::Type::getInt8Ty(VMContext);
5117 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
5118 // Non-GC overrides those files which specify GC.
5119 Mod.addModuleFlag(llvm::Module::Error,
5120 "Objective-
C Garbage Collection
",
5121 llvm::ConstantInt::get(Int8Ty,0));
5123 // Add the ObjC garbage collection value.
5124 Mod.addModuleFlag(llvm::Module::Error,
5125 "Objective-
C Garbage Collection
",
5126 llvm::ConstantInt::get(Int8Ty,
5127 (uint8_t)eImageInfo_GarbageCollected));
5129 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
5130 // Add the ObjC GC Only value.
5131 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C GC Only
",
5134 // Require that GC be specified and set to eImageInfo_GarbageCollected.
5135 llvm::Metadata *Ops[2] = {
5136 llvm::MDString::get(VMContext, "Objective-
C Garbage Collection
"),
5137 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
5138 Int8Ty, eImageInfo_GarbageCollected))};
5139 Mod.addModuleFlag(llvm::Module::Require, "Objective-
C GC Only
",
5140 llvm::MDNode::get(VMContext, Ops));
5144 // Indicate whether we're compiling this to run on a simulator.
5145 if (CGM.getTarget().getTriple().isSimulatorEnvironment())
5146 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Is Simulated
",
5147 eImageInfo_ImageIsSimulated);
5149 // Indicate whether we are generating class properties.
5150 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Class Properties
",
5151 eImageInfo_ClassProperties);
5154// struct objc_module {
5155// unsigned long version;
5156// unsigned long size;
5161// FIXME: Get from somewhere
5162static const int ModuleVersion = 7;
5164void CGObjCMac::EmitModuleInfo() {
5165 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
5167 ConstantInitBuilder builder(CGM);
5168 auto values = builder.beginStruct(ObjCTypes.ModuleTy);
5169 values.addInt(ObjCTypes.LongTy, ModuleVersion);
5170 values.addInt(ObjCTypes.LongTy, Size);
5171 // This used to be the filename, now it is unused. <rdr://4327263>
5172 values.add(GetClassName(StringRef("")));
5173 values.add(EmitModuleSymbols());
5174 CreateMetadataVar("OBJC_MODULES
", values,
5175 "__OBJC,__module_info,regular,no_dead_strip
",
5176 CGM.getPointerAlign(), true);
5179llvm::Constant *CGObjCMac::EmitModuleSymbols() {
5180 unsigned NumClasses = DefinedClasses.size();
5181 unsigned NumCategories = DefinedCategories.size();
5183 // Return null if no symbols were defined.
5184 if (!NumClasses && !NumCategories)
5185 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
5187 ConstantInitBuilder builder(CGM);
5188 auto values = builder.beginStruct();
5189 values.addInt(ObjCTypes.LongTy, 0);
5190 values.addNullPointer(ObjCTypes.SelectorPtrTy);
5191 values.addInt(ObjCTypes.ShortTy, NumClasses);
5192 values.addInt(ObjCTypes.ShortTy, NumCategories);
5194 // The runtime expects exactly the list of defined classes followed
5195 // by the list of defined categories, in a single array.
5196 auto array = values.beginArray(ObjCTypes.Int8PtrTy);
5197 for (unsigned i=0; i<NumClasses; i++) {
5198 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
5200 if (ObjCImplementationDecl *IMP = ID->getImplementation())
5201 // We are implementing a weak imported interface. Give it external linkage
5202 if (ID->isWeakImported() && !IMP->isWeakImported())
5203 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
5205 array.addBitCast(DefinedClasses[i], ObjCTypes.Int8PtrTy);
5207 for (unsigned i=0; i<NumCategories; i++)
5208 array.addBitCast(DefinedCategories[i], ObjCTypes.Int8PtrTy);
5210 array.finishAndAddTo(values);
5212 llvm::GlobalVariable *GV = CreateMetadataVar(
5213 "OBJC_SYMBOLS
", values, "__OBJC,__symbols,regular,no_dead_strip
",
5214 CGM.getPointerAlign(), true);
5215 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
5218llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
5219 IdentifierInfo *II) {
5220 LazySymbols.insert(II);
5222 llvm::GlobalVariable *&Entry = ClassReferences[II];
5225 llvm::Constant *Casted =
5226 llvm::ConstantExpr::getBitCast(GetClassName(II->getName()),
5227 ObjCTypes.ClassPtrTy);
5228 Entry = CreateMetadataVar(
5229 "OBJC_CLASS_REFERENCES_
", Casted,
5230 "__OBJC,__cls_refs,literal_pointers,no_dead_strip
",
5231 CGM.getPointerAlign(), true);
5234 return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry,
5235 CGF.getPointerAlign());
5238llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
5239 const ObjCInterfaceDecl *ID) {
5240 // If the class has the objc_runtime_visible attribute, we need to
5241 // use the Objective-C runtime to get the class.
5242 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
5243 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
5245 IdentifierInfo *RuntimeName =
5246 &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
5247 return EmitClassRefFromId(CGF, RuntimeName);
5250llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
5251 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool
");
5252 return EmitClassRefFromId(CGF, II);
5255llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
5256 return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel));
5259Address CGObjCMac::EmitSelectorAddr(Selector Sel) {
5260 CharUnits Align = CGM.getPointerAlign();
5262 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
5264 llvm::Constant *Casted =
5265 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
5266 ObjCTypes.SelectorPtrTy);
5267 Entry = CreateMetadataVar(
5268 "OBJC_SELECTOR_REFERENCES_
", Casted,
5269 "__OBJC,__message_refs,literal_pointers,no_dead_strip
", Align, true);
5270 Entry->setExternallyInitialized(true);
5273 return Address(Entry, ObjCTypes.SelectorPtrTy, Align);
5276llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
5277 llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
5279 Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
5280 return getConstantGEP(VMContext, Entry, 0, 0);
5283llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
5284 return MethodDefinitions.lookup(MD);
5289llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
5290 const ObjCCommonTypesHelper &ObjCTypes) {
5291 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
5294void IvarLayoutBuilder::visitRecord(const RecordType *RT,
5296 const RecordDecl *RD = RT->getDecl();
5298 // If this is a union, remember that we had one, because it might mess
5299 // up the ordering of layout entries.
5301 IsDisordered = true;
5303 const ASTRecordLayout *recLayout = nullptr;
5304 visitAggregate(RD->field_begin(), RD->field_end(), offset,
5305 [&](const FieldDecl *field) -> CharUnits {
5307 recLayout = &CGM.getContext().getASTRecordLayout(RD);
5308 auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex());
5309 return CGM.getContext().toCharUnitsFromBits(offsetInBits);
5313template <class Iterator, class GetOffsetFn>
5314void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
5315 CharUnits aggregateOffset,
5316 const GetOffsetFn &getOffset) {
5317 for (; begin != end; ++begin) {
5318 auto field = *begin;
5320 // Skip over bitfields.
5321 if (field->isBitField()) {
5325 // Compute the offset of the field within the aggregate.
5326 CharUnits fieldOffset = aggregateOffset + getOffset(field);
5328 visitField(field, fieldOffset);
5333void IvarLayoutBuilder::visitField(const FieldDecl *field,
5334 CharUnits fieldOffset) {
5335 QualType fieldType = field->getType();
5337 // Drill down into arrays.
5338 uint64_t numElts = 1;
5339 if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) {
5341 fieldType = arrayType->getElementType();
5343 // Unlike incomplete arrays, constant arrays can be nested.
5344 while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
5345 numElts *= arrayType->getSize().getZExtValue();
5346 fieldType = arrayType->getElementType();
5349 assert(!fieldType->isArrayType() && "ivar of non-constant array
type?
");
5351 // If we ended up with a zero-sized array, we've done what we can do within
5352 // the limits of this layout encoding.
5353 if (numElts == 0) return;
5355 // Recurse if the base element type is a record type.
5356 if (auto recType = fieldType->getAs<RecordType>()) {
5357 size_t oldEnd = IvarsInfo.size();
5359 visitRecord(recType, fieldOffset);
5361 // If we have an array, replicate the first entry's layout information.
5362 auto numEltEntries = IvarsInfo.size() - oldEnd;
5363 if (numElts != 1 && numEltEntries != 0) {
5364 CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
5365 for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
5366 // Copy the last numEltEntries onto the end of the array, adjusting
5367 // each for the element size.
5368 for (size_t i = 0; i != numEltEntries; ++i) {
5369 auto firstEntry = IvarsInfo[oldEnd + i];
5370 IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
5371 firstEntry.SizeInWords));
5379 // Classify the element type.
5380 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
5382 // If it matches what we're looking for, add an entry.
5383 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
5384 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
5385 assert(CGM.getContext().getTypeSizeInChars(fieldType)
5386 == CGM.getPointerSize());
5387 IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
5394llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
5395 llvm::SmallVectorImpl<unsigned char> &buffer) {
5396 // The bitmap is a series of skip/scan instructions, aligned to word
5397 // boundaries. The skip is performed first.
5398 const unsigned char MaxNibble = 0xF;
5399 const unsigned char SkipMask = 0xF0, SkipShift = 4;
5400 const unsigned char ScanMask = 0x0F, ScanShift = 0;
5402 assert(!IvarsInfo.empty() && "generating bitmap
for no data
");
5404 // Sort the ivar info on byte position in case we encounterred a
5405 // union nested in the ivar list.
5407 // This isn't a stable sort, but our algorithm should handle it fine.
5408 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
5410 assert(llvm::is_sorted(IvarsInfo));
5412 assert(IvarsInfo.back().Offset < InstanceEnd);
5414 assert(buffer.empty());
5416 // Skip the next N words.
5417 auto skip = [&](unsigned numWords) {
5418 assert(numWords > 0);
5420 // Try to merge into the previous byte. Since scans happen second, we
5421 // can't do this if it includes a scan.
5422 if (!buffer.empty() && !(buffer.back() & ScanMask)) {
5423 unsigned lastSkip = buffer.back() >> SkipShift;
5424 if (lastSkip < MaxNibble) {
5425 unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
5426 numWords -= claimed;
5427 lastSkip += claimed;
5428 buffer.back() = (lastSkip << SkipShift);
5432 while (numWords >= MaxNibble) {
5433 buffer.push_back(MaxNibble << SkipShift);
5434 numWords -= MaxNibble;
5437 buffer.push_back(numWords << SkipShift);
5441 // Scan the next N words.
5442 auto scan = [&](unsigned numWords) {
5443 assert(numWords > 0);
5445 // Try to merge into the previous byte. Since scans happen second, we can
5446 // do this even if it includes a skip.
5447 if (!buffer.empty()) {
5448 unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
5449 if (lastScan < MaxNibble) {
5450 unsigned claimed = std::min(MaxNibble - lastScan, numWords);
5451 numWords -= claimed;
5452 lastScan += claimed;
5453 buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
5457 while (numWords >= MaxNibble) {
5458 buffer.push_back(MaxNibble << ScanShift);
5459 numWords -= MaxNibble;
5462 buffer.push_back(numWords << ScanShift);
5466 // One past the end of the last scan.
5467 unsigned endOfLastScanInWords = 0;
5468 const CharUnits WordSize = CGM.getPointerSize();
5470 // Consider all the scan requests.
5471 for (auto &request : IvarsInfo) {
5472 CharUnits beginOfScan = request.Offset - InstanceBegin;
5474 // Ignore scan requests that don't start at an even multiple of the
5475 // word size. We can't encode them.
5476 if ((beginOfScan % WordSize) != 0) continue;
5478 // Ignore scan requests that start before the instance start.
5479 // This assumes that scans never span that boundary. The boundary
5480 // isn't the true start of the ivars, because in the fragile-ARC case
5481 // it's rounded up to word alignment, but the test above should leave
5482 // us ignoring that possibility.
5483 if (beginOfScan.isNegative()) {
5484 assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
5488 unsigned beginOfScanInWords = beginOfScan / WordSize;
5489 unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
5491 // If the scan starts some number of words after the last one ended,
5493 if (beginOfScanInWords > endOfLastScanInWords) {
5494 skip(beginOfScanInWords - endOfLastScanInWords);
5496 // Otherwise, start scanning where the last left off.
5498 beginOfScanInWords = endOfLastScanInWords;
5500 // If that leaves us with nothing to scan, ignore this request.
5501 if (beginOfScanInWords >= endOfScanInWords) continue;
5504 // Scan to the end of the request.
5505 assert(beginOfScanInWords < endOfScanInWords);
5506 scan(endOfScanInWords - beginOfScanInWords);
5507 endOfLastScanInWords = endOfScanInWords;
5511 return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
5513 // For GC layouts, emit a skip to the end of the allocation so that we
5514 // have precise information about the entire thing. This isn't useful
5515 // or necessary for the ARC-style layout strings.
5516 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
5517 unsigned lastOffsetInWords =
5518 (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
5519 if (lastOffsetInWords > endOfLastScanInWords) {
5520 skip(lastOffsetInWords - endOfLastScanInWords);
5524 // Null terminate the string.
5525 buffer.push_back(0);
5527 auto *Entry = CGObjC.CreateCStringLiteral(
5528 reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName);
5529 return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
5549CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
5550 CharUnits beginOffset, CharUnits endOffset,
5551 bool ForStrongLayout, bool HasMRCWeakIvars) {
5552 // If this is MRC, and we're either building a strong layout or there
5553 // are no weak ivars, bail out early.
5554 llvm::Type *PtrTy = CGM.Int8PtrTy;
5555 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
5556 !CGM.getLangOpts().ObjCAutoRefCount &&
5557 (ForStrongLayout || !HasMRCWeakIvars))
5558 return llvm::Constant::getNullValue(PtrTy);
5560 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
5561 SmallVector<const ObjCIvarDecl*, 32> ivars;
5563 // GC layout strings include the complete object layout, possibly
5564 // inaccurately in the non-fragile ABI; the runtime knows how to fix this
5567 // ARC layout strings only include the class's ivars. In non-fragile
5568 // runtimes, that means starting at InstanceStart, rounded up to word
5569 // alignment. In fragile runtimes, there's no InstanceStart, so it means
5570 // starting at the offset of the first ivar, rounded up to word alignment.
5572 // MRC weak layout strings follow the ARC style.
5573 CharUnits baseOffset;
5574 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
5575 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
5576 IVD; IVD = IVD->getNextIvar())
5577 ivars.push_back(IVD);
5579 if (isNonFragileABI()) {
5580 baseOffset = beginOffset; // InstanceStart
5581 } else if (!ivars.empty()) {
5583 CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
5585 baseOffset = CharUnits::Zero();
5588 baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
5591 CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
5593 baseOffset = CharUnits::Zero();
5597 return llvm::Constant::getNullValue(PtrTy);
5599 IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
5601 builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
5602 [&](const ObjCIvarDecl *ivar) -> CharUnits {
5603 return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar));
5606 if (!builder.hasBitmapData())
5607 return llvm::Constant::getNullValue(PtrTy);
5609 llvm::SmallVector<unsigned char, 4> buffer;
5610 llvm::Constant *C = builder.buildBitmap(*this, buffer);
5612 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
5613 printf("\n%
s ivar layout
for class '%s':
",
5614 ForStrongLayout ? "strong
" : "weak
",
5615 OMD->getClassInterface()->getName().str().c_str());
5616 builder.dump(buffer);
5621llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
5622 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
5623 // FIXME: Avoid std::string in "Sel.
getAsString()
"
5625 Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
5626 return getConstantGEP(VMContext, Entry, 0, 0);
5629// FIXME: Merge into a single cstring creation function.
5630llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
5631 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
5634llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
5635 std::string TypeStr;
5636 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
5638 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
5640 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
5641 return getConstantGEP(VMContext, Entry, 0, 0);
5644llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
5646 std::string TypeStr =
5647 CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
5649 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
5651 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
5652 return getConstantGEP(VMContext, Entry, 0, 0);
5655// FIXME: Merge into a single cstring creation function.
5656llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
5657 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
5659 Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
5660 return getConstantGEP(VMContext, Entry, 0, 0);
5663// FIXME: Merge into a single cstring creation function.
5664// FIXME: This Decl should be more precise.
5666CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
5667 const Decl *Container) {
5668 std::string TypeStr =
5669 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
5670 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
5673void CGObjCMac::FinishModule() {
5676 // Emit the dummy bodies for any protocols which were referenced but
5678 for (auto &entry : Protocols) {
5679 llvm::GlobalVariable *global = entry.second;
5680 if (global->hasInitializer())
5683 ConstantInitBuilder builder(CGM);
5684 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
5685 values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
5686 values.add(GetClassName(entry.first->getName()));
5687 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
5688 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5689 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5690 values.finishAndSetAsInitializer(global);
5691 CGM.addCompilerUsedGlobal(global);
5694 // Add assembler directives to add lazy undefined symbol references
5695 // for classes which are referenced but not defined. This is
5696 // important for correct linker interaction.
5698 // FIXME: It would be nice if we had an LLVM construct for this.
5699 if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
5700 CGM.getTriple().isOSBinFormatMachO()) {
5701 SmallString<256> Asm;
5702 Asm += CGM.getModule().getModuleInlineAsm();
5703 if (!Asm.empty() && Asm.back() != '\n')
5706 llvm::raw_svector_ostream OS(Asm);
5707 for (const auto *Sym : DefinedSymbols)
5708 OS << "\t.objc_class_name_
" << Sym->getName() << "=0\n
"
5709 << "\t.globl .objc_class_name_
" << Sym->getName() << "\n
";
5710 for (const auto *Sym : LazySymbols)
5711 OS << "\t.lazy_reference .objc_class_name_
" << Sym->getName() << "\n
";
5712 for (const auto &Category : DefinedCategoryNames)
5713 OS << "\t.objc_category_name_
" << Category << "=0\n
"
5714 << "\t.globl .objc_category_name_
" << Category << "\n
";
5716 CGM.getModule().setModuleInlineAsm(OS.str());
5720CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
5721 : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
5722 ObjCEmptyVtableVar(nullptr) {
5728ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
5729 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr)
5731 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5732 ASTContext &Ctx = CGM.getContext();
5733 unsigned ProgramAS = CGM.getDataLayout().getProgramAddressSpace();
5735 ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
5737 LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
5738 Int8PtrTy = CGM.Int8PtrTy;
5739 Int8PtrProgramASTy = llvm::PointerType::get(CGM.Int8Ty, ProgramAS);
5740 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
5742 // arm64 targets use "int" ivar offset variables. All others,
5743 // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
5744 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
5745 IvarOffsetVarTy = IntTy;
5747 IvarOffsetVarTy = LongTy;
5750 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
5752 llvm::PointerType::getUnqual(ObjectPtrTy);
5754 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
5756 // I'm not sure I like this. The implicit coordination is a bit
5757 // gross. We should solve this in a reasonable fashion because this
5758 // is a pretty common task (match some runtime data structure with
5759 // an LLVM data structure).
5761 // FIXME: This is leaked.
5762 // FIXME: Merge with rewriter code?
5764 // struct _objc_super {
5768 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
5769 Ctx.getTranslationUnitDecl(),
5770 SourceLocation(), SourceLocation(),
5771 &Ctx.Idents.get("_objc_super
"));
5772 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5773 nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
5774 false, ICIS_NoInit));
5775 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5776 nullptr, Ctx.getObjCClassType(), nullptr,
5777 nullptr, false, ICIS_NoInit));
5778 RD->completeDefinition();
5780 SuperCTy = Ctx.getTagDeclType(RD);
5781 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
5783 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
5784 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
5788 // char *attributes;
5790 PropertyTy = llvm::StructType::create("struct._prop_t
", Int8PtrTy, Int8PtrTy);
5792 // struct _prop_list_t {
5793 // uint32_t entsize; // sizeof(struct _prop_t)
5794 // uint32_t count_of_properties;
5795 // struct _prop_t prop_list[count_of_properties];