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;
904 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
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;
1419 llvm::DenseSet<Selector> VTableDispatchMethods;
1422 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1426 bool isVTableDispatchedSelector(
Selector Sel);
1430 void FinishNonFragileABIModule();
1435 StringRef SymbolName, StringRef SectionName);
1437 llvm::GlobalVariable * BuildClassRoTInitializer(
unsigned flags,
1438 unsigned InstanceStart,
1439 unsigned InstanceSize,
1443 llvm::Constant *IsAGV,
1444 llvm::Constant *SuperClassGV,
1445 llvm::Constant *ClassRoGV,
1454 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1466 unsigned long int offset);
1481 llvm::Constant *EmitProtocolList(Twine Name,
1489 llvm::Value *Receiver,
1497 llvm::Constant *GetClassGlobal(StringRef Name,
1499 bool Weak =
false,
bool DLLImport =
false);
1508 llvm::GlobalVariable *Entry);
1519 llvm::Value *EmitNSAutoreleasePoolClassRef(
CodeGenFunction &CGF)
override;
1534 llvm::GlobalVariable * ObjCIvarOffsetVariable(
1548 StringRef getMetaclassSymbolPrefix()
const {
return "OBJC_METACLASS_$_"; }
1550 StringRef getClassSymbolPrefix()
const {
return "OBJC_CLASS_$_"; }
1553 uint32_t &InstanceStart,
1554 uint32_t &InstanceSize);
1569 bool ImplementationIsNonLazy(
const ObjCImplDecl *OD)
const;
1588 dyn_cast_or_null<ObjCMethodDecl>(CGF.
CurFuncDecl))
1589 if (MD->isInstanceMethod() && !MD->isDirectMethod())
1598 for (;
ID;
ID =
ID->getSuperClass()) {
1601 if (
ID->getIdentifier()->getName() ==
"NSObject")
1606 if (!
ID->getImplementation())
1615 llvm::Constant *getNSConstantStringClassRef()
override;
1617 llvm::Function *ModuleInitFunction()
override;
1622 llvm::Value *Receiver,
1631 bool isCategoryImpl, llvm::Value *Receiver,
1639 {
return EmitSelector(CGF, Sel); }
1641 {
return EmitSelectorAddr(Sel); }
1647 {
return EmitSelector(CGF, Method->
getSelector()); }
1658 llvm::Constant *GetEHType(
QualType T)
override;
1660 llvm::FunctionCallee GetPropertyGetFunction()
override {
1661 return ObjCTypes.getGetPropertyFn();
1663 llvm::FunctionCallee GetPropertySetFunction()
override {
1664 return ObjCTypes.getSetPropertyFn();
1667 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
1668 bool copy)
override {
1669 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1672 llvm::FunctionCallee GetSetStructFunction()
override {
1673 return ObjCTypes.getCopyStructFn();
1676 llvm::FunctionCallee GetGetStructFunction()
override {
1677 return ObjCTypes.getCopyStructFn();
1680 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override {
1681 return ObjCTypes.getCppAtomicObjectFunction();
1684 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override {
1685 return ObjCTypes.getCppAtomicObjectFunction();
1688 llvm::FunctionCallee EnumerationMutationFunction()
override {
1689 return ObjCTypes.getEnumerationMutationFn();
1697 bool ClearInsertionPoint=
true)
override;
1699 Address AddrWeakObj)
override;
1701 llvm::Value *src,
Address edst)
override;
1703 llvm::Value *src,
Address dest,
1704 bool threadlocal =
false)
override;
1706 llvm::Value *src,
Address dest,
1707 llvm::Value *ivarOffset)
override;
1709 llvm::Value *src,
Address dest)
override;
1712 llvm::Value *size)
override;
1715 unsigned CVRQualifiers)
override;
1723struct NullReturnState {
1724 llvm::BasicBlock *NullBB =
nullptr;
1725 NullReturnState() =
default;
1738 CGF.
Builder.CreateCondBr(isNull, NullBB, callBB);
1753 if (!NullBB)
return result;
1757 llvm::BasicBlock *contBB =
nullptr;
1760 llvm::BasicBlock *callBB = CGF.
Builder.GetInsertBlock();
1775 assert(CGF.
Builder.GetInsertBlock() == NullBB);
1795 llvm::PHINode *phi = CGF.
Builder.CreatePHI(null->getType(), 2);
1797 phi->addIncoming(null, NullBB);
1806 assert(result.
isAggregate() &&
"null init of non-aggregate result?");
1815 CodeGenFunction::ComplexPairTy callResult = result.
getComplexVal();
1818 llvm::Type *scalarTy = callResult.first->getType();
1819 llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
1822 llvm::PHINode *real = CGF.
Builder.CreatePHI(scalarTy, 2);
1823 real->addIncoming(callResult.first, callBB);
1824 real->addIncoming(scalarZero, NullBB);
1825 llvm::PHINode *imag = CGF.
Builder.CreatePHI(scalarTy, 2);
1826 imag->addIncoming(callResult.second, callBB);
1827 imag->addIncoming(scalarZero, NullBB);
1838 llvm::GlobalVariable *
C,
unsigned idx0,
1840 llvm::Value *Idxs[] = {
1841 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1842 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
1844 return llvm::ConstantExpr::getGetElementPtr(
C->getValueType(),
C, Idxs);
1851 if (OID->
hasAttr<ObjCExceptionAttr>())
1858static llvm::GlobalValue::LinkageTypes
1860 if (CGM.
getTriple().isOSBinFormatMachO() &&
1861 (Section.empty() || Section.starts_with(
"__DATA")))
1862 return llvm::GlobalValue::InternalLinkage;
1863 return llvm::GlobalValue::PrivateLinkage;
1867static llvm::GlobalVariable *
1870 std::string SectionName;
1871 if (CGM.
getTriple().isOSBinFormatMachO())
1872 SectionName =
"__DATA, __objc_const";
1873 auto *GV = Builder.finishAndCreateGlobal(
1876 GV->setSection(SectionName);
1892 return EmitClassRef(CGF, ID);
1897 return EmitSelector(CGF, Sel);
1900 return EmitSelectorAddr(Sel);
1907llvm::Constant *CGObjCMac::GetEHType(
QualType T) {
1921 llvm_unreachable(
"asking for catch type for ObjC type in fragile runtime");
1944CGObjCCommonMac::GenerateConstantString(
const StringLiteral *SL) {
1947 : GenerateConstantNSString(SL));
1950static llvm::StringMapEntry<llvm::GlobalVariable *> &
1953 StringRef String = Literal->getString();
1954 StringLength = String.size();
1955 return *Map.insert(std::make_pair(String,
nullptr)).first;
1958llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
1959 if (llvm::Value *
V = ConstantStringClassRef)
1960 return cast<llvm::Constant>(
V);
1964 StringClass.empty() ?
"_NSConstantStringClassReference"
1965 :
"_" + StringClass +
"ClassReference";
1967 llvm::Type *PTy = llvm::ArrayType::get(CGM.
IntTy, 0);
1969 ConstantStringClassRef = GV;
1973llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
1974 if (llvm::Value *
V = ConstantStringClassRef)
1975 return cast<llvm::Constant>(
V);
1979 StringClass.empty() ?
"OBJC_CLASS_$_NSConstantString"
1980 :
"OBJC_CLASS_$_" + StringClass;
1982 ConstantStringClassRef = GV;
1987CGObjCCommonMac::GenerateConstantNSString(
const StringLiteral *Literal) {
1988 unsigned StringLength = 0;
1989 llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
1992 if (
auto *
C = Entry.second)
1997 llvm::Constant *
Class = getNSConstantStringClassRef();
2000 if (!NSConstantStringType) {
2001 NSConstantStringType =
2003 "struct.__builtin_NSString");
2007 auto Fields = Builder.beginStruct(NSConstantStringType);
2014 llvm::ConstantDataArray::getString(VMContext, Entry.first());
2016 llvm::GlobalValue::LinkageTypes
Linkage = llvm::GlobalValue::PrivateLinkage;
2017 bool isConstant = !CGM.
getLangOpts().WritableStrings;
2019 auto *GV =
new llvm::GlobalVariable(CGM.
getModule(),
C->getType(), isConstant,
2021 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2024 GV->setAlignment(llvm::Align(1));
2028 Fields.addInt(CGM.
IntTy, StringLength);
2032 GV = Fields.finishAndCreateGlobal(
"_unnamed_nsstring_", Alignment,
2034 llvm::GlobalVariable::PrivateLinkage);
2035 const char *NSStringSection =
"__OBJC,__cstring_object,regular,no_dead_strip";
2036 const char *NSStringNonFragileABISection =
2037 "__DATA,__objc_stringobj,regular,no_dead_strip";
2040 ? NSStringNonFragileABISection
2060 bool isCategoryImpl,
2061 llvm::Value *Receiver,
2062 bool IsClassMessage,
2069 llvm::Value *ReceiverAsObject =
2070 CGF.
Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
2075 llvm::Type *ClassTyPtr = llvm::PointerType::getUnqual(ObjCTypes.ClassTy);
2077 if (IsClassMessage) {
2078 if (isCategoryImpl) {
2085 Target = EmitClassRef(CGF,
Class->getSuperClass());
2090 llvm::Constant *MetaClassPtr = EmitMetaClassRef(
Class);
2091 llvm::Value *SuperPtr =
2097 }
else if (isCategoryImpl)
2098 Target = EmitClassRef(CGF,
Class->getSuperClass());
2100 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
2107 llvm::Type *ClassTy =
2111 return EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper.
getPointer(),
2112 ObjCTypes.SuperPtrCTy,
true, CallArgs, Method, Class,
2121 llvm::Value *Receiver,
2125 return EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
2127 Method, Class, ObjCTypes);
2141 const ObjCCommonTypesHelper &ObjCTypes) {
2144 llvm::Value *SelValue = llvm::UndefValue::get(Types.ConvertType(selTy));
2148 Arg0 = CGF.
Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
2155 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
2160 "Result type mismatch!");
2162 bool ReceiverCanBeNull =
2163 canMessageReceiverBeNull(CGF, Method, IsSuper, ClassReceiver, Arg0);
2165 bool RequiresNullCheck =
false;
2166 bool RequiresSelValue =
true;
2168 llvm::FunctionCallee
Fn =
nullptr;
2174 RequiresSelValue =
false;
2176 if (ReceiverCanBeNull) RequiresNullCheck =
true;
2177 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
2178 : ObjCTypes.getSendStretFn(IsSuper);
2180 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
2181 : ObjCTypes.getSendFpretFn(IsSuper);
2183 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
2184 : ObjCTypes.getSendFp2retFn(IsSuper);
2189 RequiresNullCheck =
true;
2190 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
2191 : ObjCTypes.getSendFn(IsSuper);
2195 llvm::Constant *BitcastFn = cast<llvm::Constant>(
2196 CGF.
Builder.CreateBitCast(
Fn.getCallee(), MSI.MessengerType));
2201 RequiresNullCheck =
false;
2205 RequiresNullCheck =
true;
2207 NullReturnState nullReturn;
2208 if (RequiresNullCheck) {
2209 nullReturn.init(CGF, Arg0);
2213 if (RequiresSelValue) {
2214 SelValue = GetSelector(CGF, Sel);
2218 llvm::CallBase *CallSite;
2220 RValue rvalue = CGF.
EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
2225 if (Method && Method->
hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
2226 CallSite->setDoesNotReturn();
2229 return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs,
2230 RequiresNullCheck ? Method :
nullptr);
2234 bool pointee =
false) {
2247 switch (ownership) {
2254 llvm_unreachable(
"bad objc ownership");
2262 if (Ctx.
getLangOpts().getGC() != LangOptions::NonGC) {
2274 IvarInfo(
CharUnits offset, uint64_t sizeInWords)
2275 : Offset(offset), SizeInWords(sizeInWords) {}
2278 bool operator<(
const IvarInfo &other)
const {
2279 return Offset < other.Offset;
2284 class IvarLayoutBuilder {
2295 bool ForStrongLayout;
2298 bool IsDisordered =
false;
2304 CharUnits instanceEnd,
bool forStrongLayout)
2305 : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
2306 ForStrongLayout(forStrongLayout) {
2311 template <
class Iterator,
class GetOffsetFn>
2312 void visitAggregate(Iterator begin, Iterator end,
2314 const GetOffsetFn &getOffset);
2322 bool hasBitmapData()
const {
return !IvarsInfo.empty(); }
2324 llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
2328 const unsigned char *
s = buffer.data();
2329 for (
unsigned i = 0, e = buffer.size(); i < e; i++)
2331 printf(
"0x0%x%s",
s[i],
s[i] != 0 ?
", " :
"");
2333 printf(
"0x%x%s",
s[i],
s[i] != 0 ?
", " :
"");
2339llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(
CodeGenModule &CGM,
2342 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2343 if (CGM.
getLangOpts().getGC() == LangOptions::NonGC)
2349 builder.visitBlock(blockInfo);
2351 if (!builder.hasBitmapData())
2355 llvm::Constant *
C = builder.buildBitmap(*
this, buffer);
2356 if (CGM.
getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
2357 printf(
"\n block variable layout for block: ");
2358 builder.dump(buffer);
2364void IvarLayoutBuilder::visitBlock(
const CGBlockInfo &blockInfo) {
2377 for (
const auto &CI :
blockDecl->captures()) {
2378 const VarDecl *variable = CI.getVariable();
2390 if (fieldOffset < lastFieldOffset)
2391 IsDisordered =
true;
2392 lastFieldOffset = fieldOffset;
2396 IvarsInfo.push_back(IvarInfo(fieldOffset, 1));
2400 assert(!
type->isArrayType() &&
"array variable should not be caught");
2402 visitRecord(record, fieldOffset);
2411 IvarsInfo.push_back(IvarInfo(fieldOffset, 1));
2436void CGObjCCommonMac::UpdateRunSkipBlockVars(
bool IsByref,
2442 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
2445 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
2448 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
2451 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
2454 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2459void CGObjCCommonMac::BuildRCRecordLayout(
const llvm::StructLayout *RecLayout,
2464 bool IsUnion = (RD && RD->
isUnion());
2467 const FieldDecl *LastFieldBitfieldOrUnnamed =
nullptr;
2471 if (RecFields.empty())
2475 for (
unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2484 if (!
Field->getIdentifier() ||
Field->isBitField()) {
2485 LastFieldBitfieldOrUnnamed =
Field;
2486 LastBitfieldOrUnnamedOffset = FieldOffset;
2490 LastFieldBitfieldOrUnnamed =
nullptr;
2497 BytePos + FieldOffset, HasUnion);
2502 auto *CArray = cast<ConstantArrayType>(Array);
2503 uint64_t ElCount = CArray->getZExtSize();
2504 assert(CArray &&
"only array with known element size is supported");
2505 FQT = CArray->getElementType();
2507 auto *CArray = cast<ConstantArrayType>(Array);
2508 ElCount *= CArray->getZExtSize();
2509 FQT = CArray->getElementType();
2512 int OldIndex = RunSkipBlockVars.size() - 1;
2514 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset, HasUnion);
2519 for (
int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
2521 for (
int i = OldIndex+1; i <= FirstIndex; ++i)
2522 RunSkipBlockVars.push_back(
2523 RUN_SKIP(RunSkipBlockVars[i].opcode,
2524 RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
2525 RunSkipBlockVars[i].block_var_size));
2533 if (UnionIvarSize > MaxUnionSize) {
2534 MaxUnionSize = UnionIvarSize;
2536 MaxFieldOffset = FieldOffset;
2539 UpdateRunSkipBlockVars(
false,
2540 getBlockCaptureLifetime(FQT, ByrefLayout),
2541 BytePos + FieldOffset,
2546 if (LastFieldBitfieldOrUnnamed) {
2547 if (LastFieldBitfieldOrUnnamed->
isBitField()) {
2551 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
2552 ((BitFieldSize % ByteSizeInBits) != 0);
2554 Size += LastBitfieldOrUnnamedOffset;
2555 UpdateRunSkipBlockVars(
false,
2556 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->
getType(),
2558 BytePos + LastBitfieldOrUnnamedOffset,
2561 assert(!LastFieldBitfieldOrUnnamed->
getIdentifier() &&
"Expected unnamed");
2565 UpdateRunSkipBlockVars(
false,
2566 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->
getType(),
2568 BytePos + LastBitfieldOrUnnamedOffset,
2574 UpdateRunSkipBlockVars(
false,
2575 getBlockCaptureLifetime(MaxField->
getType(), ByrefLayout),
2576 BytePos + MaxFieldOffset,
2580void CGObjCCommonMac::BuildRCBlockVarRecordLayout(
const RecordType *RT,
2587 const llvm::StructLayout *RecLayout =
2588 CGM.
getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
2590 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
2602uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2605 if (Layout.size() <= 3) {
2606 unsigned size = Layout.size();
2607 unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
2609 enum BLOCK_LAYOUT_OPCODE opcode ;
2613 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2614 if (opcode == BLOCK_LAYOUT_STRONG)
2615 strong_word_count = (inst & 0xF)+1;
2619 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2620 if (opcode == BLOCK_LAYOUT_BYREF)
2621 byref_word_count = (inst & 0xF)+1;
2625 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2626 if (opcode == BLOCK_LAYOUT_WEAK)
2627 weak_word_count = (inst & 0xF)+1;
2634 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2635 if (opcode == BLOCK_LAYOUT_STRONG) {
2636 strong_word_count = (inst & 0xF)+1;
2638 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2639 if (opcode == BLOCK_LAYOUT_BYREF)
2640 byref_word_count = (inst & 0xF)+1;
2641 else if (opcode == BLOCK_LAYOUT_WEAK)
2642 weak_word_count = (inst & 0xF)+1;
2646 else if (opcode == BLOCK_LAYOUT_BYREF) {
2647 byref_word_count = (inst & 0xF)+1;
2649 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2650 if (opcode == BLOCK_LAYOUT_WEAK)
2651 weak_word_count = (inst & 0xF)+1;
2661 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2662 if (opcode == BLOCK_LAYOUT_STRONG)
2663 strong_word_count = (inst & 0xF)+1;
2664 else if (opcode == BLOCK_LAYOUT_BYREF)
2665 byref_word_count = (inst & 0xF)+1;
2666 else if (opcode == BLOCK_LAYOUT_WEAK)
2667 weak_word_count = (inst & 0xF)+1;
2679 if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
2683 (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
2685 if (size == count) {
2686 if (strong_word_count)
2687 Result = strong_word_count;
2689 if (byref_word_count)
2690 Result += byref_word_count;
2692 if (weak_word_count)
2693 Result += weak_word_count;
2699llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(
bool ComputeByrefLayout) {
2700 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2701 if (RunSkipBlockVars.empty())
2705 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2709 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2712 unsigned size = RunSkipBlockVars.size();
2713 for (
unsigned i = 0; i < size; i++) {
2714 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2715 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2716 CharUnits end_byte_pos = start_byte_pos;
2719 if (opcode == RunSkipBlockVars[j].opcode) {
2720 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2727 end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2730 RunSkipBlockVars[j].block_var_bytepos -
2731 RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
2732 size_in_bytes += gap;
2735 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2736 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2737 size_in_bytes -= residue_in_bytes;
2738 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2741 unsigned size_in_words = size_in_bytes.
getQuantity() / WordSizeInBytes;
2742 while (size_in_words >= 16) {
2745 unsigned char inst = (opcode << 4) | 0xf;
2746 Layout.push_back(inst);
2747 size_in_words -= 16;
2749 if (size_in_words > 0) {
2752 unsigned char inst = (opcode << 4) | (size_in_words-1);
2753 Layout.push_back(inst);
2756 unsigned char inst =
2757 (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.
getQuantity()-1);
2758 Layout.push_back(inst);
2762 while (!Layout.empty()) {
2763 unsigned char inst = Layout.back();
2764 enum BLOCK_LAYOUT_OPCODE opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2765 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2771 uint64_t Result = InlineLayoutInstruction(Layout);
2775 if (ComputeByrefLayout)
2776 printf(
"\n Inline BYREF variable layout: ");
2778 printf(
"\n Inline block variable layout: ");
2779 printf(
"0x0%" PRIx64
"", Result);
2780 if (
auto numStrong = (Result & 0xF00) >> 8)
2781 printf(
", BL_STRONG:%d", (
int) numStrong);
2782 if (
auto numByref = (Result & 0x0F0) >> 4)
2783 printf(
", BL_BYREF:%d", (
int) numByref);
2784 if (
auto numWeak = (Result & 0x00F) >> 0)
2785 printf(
", BL_WEAK:%d", (
int) numWeak);
2786 printf(
", BL_OPERATOR:0\n");
2788 return llvm::ConstantInt::get(CGM.
IntPtrTy, Result);
2791 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2792 Layout.push_back(inst);
2794 for (
unsigned i = 0, e = Layout.size(); i != e; i++)
2795 BitMap += Layout[i];
2798 if (ComputeByrefLayout)
2799 printf(
"\n Byref variable layout: ");
2801 printf(
"\n Block variable layout: ");
2802 for (
unsigned i = 0, e = BitMap.size(); i != e; i++) {
2803 unsigned char inst = BitMap[i];
2804 enum BLOCK_LAYOUT_OPCODE opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2807 case BLOCK_LAYOUT_OPERATOR:
2811 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2812 printf(
"BL_NON_OBJECT_BYTES:");
2814 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2815 printf(
"BL_NON_OBJECT_WORD:");
2817 case BLOCK_LAYOUT_STRONG:
2820 case BLOCK_LAYOUT_BYREF:
2823 case BLOCK_LAYOUT_WEAK:
2826 case BLOCK_LAYOUT_UNRETAINED:
2827 printf(
"BL_UNRETAINED:");
2832 printf(
"%d", (inst & 0xf) + delta);
2840 auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
2848 bool HasCopyDisposeHelpers) {
2850 for (
const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) {
2851 if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) {
2855 }
else if (HasCopyDisposeHelpers) {
2863 case CGObjCCommonMac::BLOCK_LAYOUT_STRONG:
2866 case CGObjCCommonMac::BLOCK_LAYOUT_BYREF:
2869 case CGObjCCommonMac::BLOCK_LAYOUT_WEAK:
2876 Str += llvm::to_string(R.block_var_bytepos.getQuantity());
2877 Str +=
"l" + llvm::to_string(R.block_var_size.getQuantity());
2882void CGObjCCommonMac::fillRunSkipBlockVars(
CodeGenModule &CGM,
2884 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
2886 RunSkipBlockVars.clear();
2887 bool hasUnion =
false;
2891 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2896 const llvm::StructLayout *layout =
2906 for (
const auto &CI :
blockDecl->captures()) {
2907 const VarDecl *variable = CI.getVariable();
2918 assert(!
type->isArrayType() &&
"array variable should not be caught");
2921 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2929 UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(
type,
false),
2930 fieldOffset, fieldSize);
2937 fillRunSkipBlockVars(CGM, blockInfo);
2938 return getBitmapBlockLayout(
false);
2941std::string CGObjCCommonMac::getRCBlockLayoutStr(
CodeGenModule &CGM,
2943 fillRunSkipBlockVars(CGM, blockInfo);
2949 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
2950 assert(!
T->
isArrayType() &&
"__block array variable should not be caught");
2952 RunSkipBlockVars.clear();
2953 bool hasUnion =
false;
2955 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion,
true );
2956 llvm::Constant *Result = getBitmapBlockLayout(
true);
2957 if (isa<llvm::ConstantInt>(Result))
2958 Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.
Int8PtrTy);
2961 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2971 return GetProtocolRef(PD);
2983 GetOrEmitProtocol(PD);
2986llvm::Constant *CGObjCCommonMac::GetProtocolRef(
const ObjCProtocolDecl *PD) {
2988 return GetOrEmitProtocol(PD);
2990 return GetOrEmitProtocolRef(PD);
2993llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime(
2996 ObjCCommonTypesHelper &ObjCTypes) {
2997 llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn();
2999 llvm::Value *className = CGF.
CGM
3001 ID->getObjCRuntimeNameAsString()))
3005 CGF.
Builder.CreateBitCast(className,
3008 llvm::CallInst *call = CGF.
Builder.CreateCall(lookUpClassFn, className);
3009 call->setDoesNotThrow();
3026 llvm::GlobalVariable *Entry = Protocols[PD->
getIdentifier()];
3029 if (Entry && Entry->hasInitializer())
3041 auto methodLists = ProtocolMethodLists::get(PD);
3044 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
3045 values.add(EmitProtocolExtension(PD, methodLists));
3047 values.add(EmitProtocolList(
"OBJC_PROTOCOL_REFS_" + PD->
getName(),
3049 values.add(methodLists.emitMethodList(
this, PD,
3050 ProtocolMethodLists::RequiredInstanceMethods));
3051 values.add(methodLists.emitMethodList(
this, PD,
3052 ProtocolMethodLists::RequiredClassMethods));
3056 assert(Entry->hasPrivateLinkage());
3057 values.finishAndSetAsInitializer(Entry);
3059 Entry = values.finishAndCreateGlobal(
"OBJC_PROTOCOL_" + PD->
getName(),
3062 llvm::GlobalValue::PrivateLinkage);
3063 Entry->setSection(
"__OBJC,__protocol,regular,no_dead_strip");
3072llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD) {
3073 llvm::GlobalVariable *&Entry = Protocols[PD->
getIdentifier()];
3079 Entry =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ProtocolTy,
3080 false, llvm::GlobalValue::PrivateLinkage,
3081 nullptr,
"OBJC_PROTOCOL_" + PD->
getName());
3082 Entry->setSection(
"__OBJC,__protocol,regular,no_dead_strip");
3084 Entry->setAlignment(llvm::Align(4));
3102 const ProtocolMethodLists &methodLists) {
3103 auto optInstanceMethods =
3104 methodLists.emitMethodList(
this, PD,
3105 ProtocolMethodLists::OptionalInstanceMethods);
3106 auto optClassMethods =
3107 methodLists.emitMethodList(
this, PD,
3108 ProtocolMethodLists::OptionalClassMethods);
3110 auto extendedMethodTypes =
3111 EmitProtocolMethodTypes(
"OBJC_PROTOCOL_METHOD_TYPES_" + PD->
getName(),
3112 methodLists.emitExtendedTypesArray(
this),
3115 auto instanceProperties =
3116 EmitPropertyList(
"OBJC_$_PROP_PROTO_LIST_" + PD->
getName(),
nullptr, PD,
3118 auto classProperties =
3119 EmitPropertyList(
"OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->
getName(),
nullptr,
3120 PD, ObjCTypes,
true);
3123 if (optInstanceMethods->isNullValue() &&
3124 optClassMethods->isNullValue() &&
3125 extendedMethodTypes->isNullValue() &&
3126 instanceProperties->isNullValue() &&
3127 classProperties->isNullValue()) {
3128 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
3132 CGM.
getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
3135 auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
3136 values.addInt(ObjCTypes.IntTy, size);
3137 values.add(optInstanceMethods);
3138 values.add(optClassMethods);
3139 values.add(instanceProperties);
3140 values.add(extendedMethodTypes);
3141 values.add(classProperties);
3144 return CreateMetadataVar(
"_OBJC_PROTOCOLEXT_" + PD->
getName(), values,
3156CGObjCMac::EmitProtocolList(Twine name,
3160 auto PDs = GetRuntimeProtocolList(begin, end);
3162 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
3165 auto values = builder.beginStruct();
3168 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
3171 auto countSlot = values.addPlaceholder();
3173 auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
3174 for (
const auto *Proto : PDs)
3175 refsArray.add(GetProtocolRef(Proto));
3177 auto count = refsArray.size();
3180 refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
3182 refsArray.finishAndAddTo(values);
3183 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
3186 if (CGM.
getTriple().isOSBinFormatMachO())
3187 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3189 llvm::GlobalVariable *GV =
3190 CreateMetadataVar(name, values, section, CGM.
getPointerAlign(),
false);
3198 bool IsClassProperty) {
3200 if (IsClassProperty != PD->isClassProperty())
3204 Properties.push_back(PD);
3223llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
3224 const Decl *Container,
3226 const ObjCCommonTypesHelper &ObjCTypes,
3227 bool IsClassProperty) {
3228 if (IsClassProperty) {
3232 if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
3233 (Triple.isiOS() && Triple.isOSVersionLT(9)))
3234 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3242 for (
auto *PD : ClassExt->properties()) {
3243 if (IsClassProperty != PD->isClassProperty())
3245 if (PD->isDirectProperty())
3248 Properties.push_back(PD);
3252 if (IsClassProperty != PD->isClassProperty())
3258 if (PD->isDirectProperty())
3260 Properties.push_back(PD);
3264 for (
const auto *
P : OID->all_referenced_protocols())
3268 for (
const auto *
P : CD->protocols())
3273 if (Properties.empty())
3274 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3276 unsigned propertySize =
3280 auto values = builder.beginStruct();
3281 values.addInt(ObjCTypes.IntTy, propertySize);
3282 values.addInt(ObjCTypes.IntTy, Properties.size());
3283 auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
3284 for (
auto PD : Properties) {
3285 auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
3287 property.add(GetPropertyTypeString(PD, Container));
3288 property.finishAndAddTo(propertiesArray);
3290 propertiesArray.finishAndAddTo(values);
3293 if (CGM.
getTriple().isOSBinFormatMachO())
3294 Section = (ObjCABI == 2) ?
"__DATA, __objc_const"
3295 :
"__OBJC,__property,regular,no_dead_strip";
3297 llvm::GlobalVariable *GV =
3298 CreateMetadataVar(Name, values, Section, CGM.
getPointerAlign(),
true);
3303CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
3305 const ObjCCommonTypesHelper &ObjCTypes) {
3307 if (MethodTypes.empty())
3308 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
3310 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3311 MethodTypes.size());
3312 llvm::Constant *
Init = llvm::ConstantArray::get(AT, MethodTypes);
3315 if (CGM.
getTriple().isOSBinFormatMachO() && ObjCABI == 2)
3316 Section =
"__DATA, __objc_const";
3318 llvm::GlobalVariable *GV =
3347 llvm::raw_svector_ostream(ExtName) <<
Interface->getName() <<
'_'
3351 auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
3359 for (
const auto *MD : OCD->
methods()) {
3360 if (!MD->isDirectMethod())
3361 Methods[
unsigned(MD->isClassMethod())].push_back(MD);
3364 Values.add(GetClassName(OCD->
getName()));
3365 Values.add(GetClassName(
Interface->getObjCRuntimeNameAsString()));
3366 LazySymbols.insert(
Interface->getIdentifier());
3368 Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
3369 Methods[InstanceMethods]));
3370 Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
3371 Methods[ClassMethods]));
3374 EmitProtocolList(
"OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
3377 Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
3379 Values.addInt(ObjCTypes.IntTy, Size);
3383 Values.add(EmitPropertyList(
"_OBJC_$_PROP_LIST_" + ExtName.str(),
3385 Values.add(EmitPropertyList(
"_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
3388 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3389 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3392 llvm::GlobalVariable *GV =
3393 CreateMetadataVar(
"OBJC_CATEGORY_" + ExtName.str(), Values,
3394 "__OBJC,__category,regular,no_dead_strip",
3396 DefinedCategories.push_back(GV);
3397 DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
3399 MethodDefinitions.clear();
3459 for (
auto *field : recType->getDecl()->fields()) {
3474 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
3477 ID->getClassInterface()->all_declared_ivar_begin();
3478 ivar; ivar = ivar->getNextIvar()) {
3508 DefinedSymbols.insert(RuntimeName);
3510 std::string ClassName =
ID->getNameAsString();
3514 llvm::Constant *Protocols =
3515 EmitProtocolList(
"OBJC_CLASS_PROTOCOLS_" +
ID->getName(),
3516 Interface->all_referenced_protocol_begin(),
3517 Interface->all_referenced_protocol_end());
3519 if (
ID->hasNonZeroConstructors() ||
ID->hasDestructors())
3522 bool hasMRCWeak =
false;
3542 for (
const auto *MD :
ID->methods()) {
3543 if (!MD->isDirectMethod())
3544 Methods[
unsigned(MD->isClassMethod())].push_back(MD);
3547 for (
const auto *PID :
ID->property_impls()) {
3549 if (PID->getPropertyDecl()->isDirectProperty())
3552 if (GetMethodDefinition(MD))
3553 Methods[InstanceMethods].push_back(MD);
3555 if (GetMethodDefinition(MD))
3556 Methods[InstanceMethods].push_back(MD);
3561 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3562 values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
3565 LazySymbols.insert(Super->getIdentifier());
3567 values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
3569 values.addNullPointer(ObjCTypes.ClassPtrTy);
3571 values.add(GetClassName(
ID->getObjCRuntimeNameAsString()));
3573 values.addInt(ObjCTypes.LongTy, 0);
3574 values.addInt(ObjCTypes.LongTy, Flags);
3575 values.addInt(ObjCTypes.LongTy,
Size.getQuantity());
3576 values.add(EmitIvarList(ID,
false));
3577 values.add(emitMethodList(
ID->getName(), MethodListType::InstanceMethods,
3578 Methods[InstanceMethods]));
3580 values.addNullPointer(ObjCTypes.CachePtrTy);
3581 values.add(Protocols);
3583 values.add(EmitClassExtension(ID, Size, hasMRCWeak,
3586 std::string Name(
"OBJC_CLASS_");
3588 const char *Section =
"__OBJC,__class,regular,no_dead_strip";
3590 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3592 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3593 "Forward metaclass reference has incorrect type.");
3594 values.finishAndSetAsInitializer(GV);
3595 GV->setSection(Section);
3599 GV = CreateMetadataVar(Name, values, Section, CGM.
getPointerAlign(),
true);
3600 DefinedClasses.push_back(GV);
3601 ImplementedClasses.push_back(
Interface);
3603 MethodDefinitions.clear();
3607 llvm::Constant *Protocols,
3616 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3626 values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
3628 values.addNullPointer(ObjCTypes.ClassPtrTy);
3630 values.add(GetClassName(
ID->getObjCRuntimeNameAsString()));
3632 values.addInt(ObjCTypes.LongTy, 0);
3633 values.addInt(ObjCTypes.LongTy, Flags);
3634 values.addInt(ObjCTypes.LongTy, Size);
3635 values.add(EmitIvarList(ID,
true));
3636 values.add(emitMethodList(
ID->getName(), MethodListType::ClassMethods,
3639 values.addNullPointer(ObjCTypes.CachePtrTy);
3640 values.add(Protocols);
3642 values.addNullPointer(ObjCTypes.Int8PtrTy);
3647 std::string Name(
"OBJC_METACLASS_");
3648 Name +=
ID->getName();
3651 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3653 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3654 "Forward metaclass reference has incorrect type.");
3655 values.finishAndSetAsInitializer(GV);
3659 llvm::GlobalValue::PrivateLinkage);
3661 GV->setSection(
"__OBJC,__meta_class,regular,no_dead_strip");
3668 std::string Name =
"OBJC_METACLASS_" +
ID->getNameAsString();
3678 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3680 GV =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ClassTy,
false,
3681 llvm::GlobalValue::PrivateLinkage,
nullptr,
3684 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3685 "Forward metaclass reference has incorrect type.");
3690 std::string Name =
"OBJC_CLASS_" +
ID->getNameAsString();
3691 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3694 GV =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ClassTy,
false,
3695 llvm::GlobalValue::PrivateLinkage,
nullptr,
3698 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3699 "Forward class metadata reference has incorrect type.");
3719 llvm::Constant *layout;
3721 layout = llvm::ConstantPointerNull::get(CGM.
Int8PtrTy);
3728 llvm::Constant *propertyList =
3729 EmitPropertyList((isMetaclass ? Twine(
"_OBJC_$_CLASS_PROP_LIST_")
3730 : Twine(
"_OBJC_$_PROP_LIST_"))
3732 ID,
ID->getClassInterface(), ObjCTypes, isMetaclass);
3735 if (layout->isNullValue() && propertyList->isNullValue()) {
3736 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
3740 CGM.
getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
3743 auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
3744 values.addInt(ObjCTypes.IntTy, size);
3746 values.add(propertyList);
3748 return CreateMetadataVar(
"OBJC_CLASSEXT_" +
ID->getName(), values,
3749 "__OBJC,__class_ext,regular,no_dead_strip",
3773 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
3778 auto ivarList = builder.beginStruct();
3779 auto countSlot = ivarList.addPlaceholder();
3780 auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
3785 if (!IVD->getDeclName())
3788 auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
3789 ivar.add(GetMethodVarName(IVD->getIdentifier()));
3790 ivar.add(GetMethodVarType(IVD));
3791 ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
3792 ivar.finishAndAddTo(ivars);
3796 auto count = ivars.size();
3800 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
3803 ivars.finishAndAddTo(ivarList);
3804 ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
3806 llvm::GlobalVariable *GV;
3807 GV = CreateMetadataVar(
"OBJC_INSTANCE_VARIABLES_" +
ID->getName(), ivarList,
3808 "__OBJC,__instance_vars,regular,no_dead_strip",
3821 auto description = builder.
beginStruct(ObjCTypes.MethodDescriptionTy);
3822 description.add(GetMethodVarName(MD->
getSelector()));
3823 description.add(GetMethodVarType(MD));
3824 description.finishAndAddTo(builder);
3836 llvm::Function *fn = GetMethodDefinition(MD);
3837 assert(fn &&
"no definition registered for method");
3839 auto method = builder.
beginStruct(ObjCTypes.MethodTy);
3841 method.add(GetMethodVarType(MD));
3843 method.finishAndAddTo(builder);
3859llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
3863 bool forProtocol =
false;
3865 case MethodListType::CategoryInstanceMethods:
3866 prefix =
"OBJC_CATEGORY_INSTANCE_METHODS_";
3867 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3868 forProtocol =
false;
3870 case MethodListType::CategoryClassMethods:
3871 prefix =
"OBJC_CATEGORY_CLASS_METHODS_";
3872 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3873 forProtocol =
false;
3875 case MethodListType::InstanceMethods:
3876 prefix =
"OBJC_INSTANCE_METHODS_";
3877 section =
"__OBJC,__inst_meth,regular,no_dead_strip";
3878 forProtocol =
false;
3880 case MethodListType::ClassMethods:
3881 prefix =
"OBJC_CLASS_METHODS_";
3882 section =
"__OBJC,__cls_meth,regular,no_dead_strip";
3883 forProtocol =
false;
3885 case MethodListType::ProtocolInstanceMethods:
3886 prefix =
"OBJC_PROTOCOL_INSTANCE_METHODS_";
3887 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3890 case MethodListType::ProtocolClassMethods:
3891 prefix =
"OBJC_PROTOCOL_CLASS_METHODS_";
3892 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3895 case MethodListType::OptionalProtocolInstanceMethods:
3896 prefix =
"OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
3897 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3900 case MethodListType::OptionalProtocolClassMethods:
3901 prefix =
"OBJC_PROTOCOL_CLASS_METHODS_OPT_";
3902 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3908 if (methods.empty())
3909 return llvm::Constant::getNullValue(forProtocol
3910 ? ObjCTypes.MethodDescriptionListPtrTy
3911 : ObjCTypes.MethodListPtrTy);
3918 values.addInt(ObjCTypes.IntTy, methods.size());
3919 auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
3920 for (
auto MD : methods) {
3921 emitMethodDescriptionConstant(methodArray, MD);
3923 methodArray.finishAndAddTo(values);
3925 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3933 values.addNullPointer(ObjCTypes.Int8PtrTy);
3934 values.addInt(ObjCTypes.IntTy, methods.size());
3935 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
3936 for (
auto MD : methods) {
3938 emitMethodConstant(methodArray, MD);
3940 methodArray.finishAndAddTo(values);
3942 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3947llvm::Function *CGObjCCommonMac::GenerateMethod(
const ObjCMethodDecl *OMD,
3949 llvm::Function *Method;
3952 Method = GenerateDirectMethod(OMD, CD);
3954 auto Name = getSymbolNameForMethod(OMD);
3957 llvm::FunctionType *MethodTy =
3958 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
3960 llvm::Function::Create(MethodTy, llvm::GlobalValue::InternalLinkage,
3964 MethodDefinitions.insert(std::make_pair(OMD, Method));
3973 auto I = DirectMethodDefinitions.find(COMD);
3974 llvm::Function *OldFn =
nullptr, *
Fn =
nullptr;
3976 if (I != DirectMethodDefinitions.end()) {
3992 llvm::FunctionType *MethodTy =
3993 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
3996 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
3998 Fn->takeName(OldFn);
3999 OldFn->replaceAllUsesWith(Fn);
4000 OldFn->eraseFromParent();
4005 auto Name = getSymbolNameForMethod(OMD,
false);
4007 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
4009 DirectMethodDefinitions.insert(std::make_pair(COMD, Fn));
4015void CGObjCCommonMac::GenerateDirectMethodPrologue(
4019 bool ReceiverCanBeNull =
true;
4021 auto selfValue = Builder.CreateLoad(selfAddr);
4039 "GenerateDirectMethod() should be called with the Class Interface");
4052 result = GeneratePossiblySpecializedMessageSend(
4060 ReceiverCanBeNull = isWeakLinkedClass(OID);
4063 if (ReceiverCanBeNull) {
4064 llvm::BasicBlock *SelfIsNilBlock =
4066 llvm::BasicBlock *ContBlock =
4070 auto selfTy = cast<llvm::PointerType>(selfValue->getType());
4071 auto Zero = llvm::ConstantPointerNull::get(selfTy);
4074 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero), SelfIsNilBlock,
4075 ContBlock, MDHelper.createUnlikelyBranchWeights());
4081 Builder.SetInsertPoint(SelfIsNilBlock);
4082 if (!retTy->isVoidType()) {
4090 Builder.SetInsertPoint(ContBlock);
4098 Builder.CreateStore(GetSelector(CGF, OMD),
4103llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
4108 llvm::GlobalValue::LinkageTypes
LT =
4110 llvm::GlobalVariable *GV =
4111 Init.finishAndCreateGlobal(Name, Align,
false,
LT);
4112 if (!Section.empty())
4113 GV->setSection(Section);
4119llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
4120 llvm::Constant *
Init,
4124 llvm::Type *Ty =
Init->getType();
4125 llvm::GlobalValue::LinkageTypes
LT =
4127 llvm::GlobalVariable *GV =
4129 if (!Section.empty())
4130 GV->setSection(Section);
4137llvm::GlobalVariable *
4138CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType
Type,
4139 bool ForceNonFragileABI,
4140 bool NullTerminate) {
4143 case ObjCLabelType::ClassName:
Label =
"OBJC_CLASS_NAME_";
break;
4144 case ObjCLabelType::MethodVarName:
Label =
"OBJC_METH_VAR_NAME_";
break;
4145 case ObjCLabelType::MethodVarType:
Label =
"OBJC_METH_VAR_TYPE_";
break;
4146 case ObjCLabelType::PropertyName:
Label =
"OBJC_PROP_NAME_ATTR_";
break;
4149 bool NonFragile = ForceNonFragileABI || isNonFragileABI();
4153 case ObjCLabelType::ClassName:
4154 Section = NonFragile ?
"__TEXT,__objc_classname,cstring_literals"
4155 :
"__TEXT,__cstring,cstring_literals";
4157 case ObjCLabelType::MethodVarName:
4158 Section = NonFragile ?
"__TEXT,__objc_methname,cstring_literals"
4159 :
"__TEXT,__cstring,cstring_literals";
4161 case ObjCLabelType::MethodVarType:
4162 Section = NonFragile ?
"__TEXT,__objc_methtype,cstring_literals"
4163 :
"__TEXT,__cstring,cstring_literals";
4165 case ObjCLabelType::PropertyName:
4166 Section = NonFragile ?
"__TEXT,__objc_methname,cstring_literals"
4167 :
"__TEXT,__cstring,cstring_literals";
4171 llvm::Constant *
Value =
4172 llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
4173 llvm::GlobalVariable *GV =
4176 llvm::GlobalValue::PrivateLinkage,
Value,
Label);
4177 if (CGM.
getTriple().isOSBinFormatMachO())
4178 GV->setSection(Section);
4179 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4186llvm::Function *CGObjCMac::ModuleInitFunction() {
4192llvm::FunctionCallee CGObjCMac::GetPropertyGetFunction() {
4193 return ObjCTypes.getGetPropertyFn();
4196llvm::FunctionCallee CGObjCMac::GetPropertySetFunction() {
4197 return ObjCTypes.getSetPropertyFn();
4200llvm::FunctionCallee CGObjCMac::GetOptimizedPropertySetFunction(
bool atomic,
4202 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
4205llvm::FunctionCallee CGObjCMac::GetGetStructFunction() {
4206 return ObjCTypes.getCopyStructFn();
4209llvm::FunctionCallee CGObjCMac::GetSetStructFunction() {
4210 return ObjCTypes.getCopyStructFn();
4213llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectGetFunction() {
4214 return ObjCTypes.getCppAtomicObjectFunction();
4217llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectSetFunction() {
4218 return ObjCTypes.getCppAtomicObjectFunction();
4221llvm::FunctionCallee CGObjCMac::EnumerationMutationFunction() {
4222 return ObjCTypes.getEnumerationMutationFn();
4226 return EmitTryOrSynchronizedStmt(CGF, S);
4231 return EmitTryOrSynchronizedStmt(CGF, S);
4240 ObjCTypesHelper &ObjCTypes;
4241 PerformFragileFinally(
const Stmt *S,
4245 ObjCTypesHelper *ObjCTypes)
4246 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
4247 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
4252 llvm::BasicBlock *FinallyCallExit =
4254 llvm::BasicBlock *FinallyNoCallExit =
4257 FinallyCallExit, FinallyNoCallExit);
4265 if (isa<ObjCAtTryStmt>(S)) {
4267 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
4269 if (flags.isForEHCleanup())
return;
4273 llvm::Value *CurCleanupDest =
4276 CGF.
EmitStmt(FinallyStmt->getFinallyBody());
4295 class FragileHazards {
4298 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
4300 llvm::InlineAsm *ReadHazard;
4301 llvm::InlineAsm *WriteHazard;
4303 llvm::FunctionType *GetAsmFnType();
4305 void collectLocals();
4311 void emitWriteHazard();
4312 void emitHazardsInNewBlocks();
4324 if (Locals.empty())
return;
4327 for (llvm::Function::iterator
4328 I = CGF.
CurFn->begin(),
E = CGF.
CurFn->end(); I !=
E; ++I)
4329 BlocksBeforeTry.insert(&*I);
4331 llvm::FunctionType *AsmFnTy = GetAsmFnType();
4339 std::string Constraint;
4340 for (
unsigned I = 0,
E = Locals.size(); I !=
E; ++I) {
4341 if (I) Constraint +=
',';
4345 ReadHazard = llvm::InlineAsm::get(AsmFnTy,
"", Constraint,
true,
false);
4353 std::string Constraint;
4354 for (
unsigned I = 0,
E = Locals.size(); I !=
E; ++I) {
4355 if (I) Constraint +=
',';
4356 Constraint +=
"=*m";
4359 WriteHazard = llvm::InlineAsm::get(AsmFnTy,
"", Constraint,
true,
false);
4364void FragileHazards::emitWriteHazard() {
4365 if (Locals.empty())
return;
4368 for (
auto Pair : llvm::enumerate(Locals))
4369 Call->addParamAttr(Pair.index(), llvm::Attribute::get(
4371 cast<llvm::AllocaInst>(Pair.value())->getAllocatedType()));
4374void FragileHazards::emitReadHazard(
CGBuilderTy &Builder) {
4375 assert(!Locals.empty());
4376 llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
4377 call->setDoesNotThrow();
4379 for (
auto Pair : llvm::enumerate(Locals))
4380 call->addParamAttr(Pair.index(), llvm::Attribute::get(
4381 Builder.getContext(), llvm::Attribute::ElementType,
4382 cast<llvm::AllocaInst>(Pair.value())->getAllocatedType()));
4387void FragileHazards::emitHazardsInNewBlocks() {
4388 if (Locals.empty())
return;
4393 for (llvm::Function::iterator
4394 FI = CGF.
CurFn->begin(), FE = CGF.
CurFn->end(); FI != FE; ++FI) {
4395 llvm::BasicBlock &BB = *FI;
4396 if (BlocksBeforeTry.count(&BB))
continue;
4399 for (llvm::BasicBlock::iterator
4400 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
4401 llvm::Instruction &I = *BI;
4405 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I))
4407 if (isa<llvm::IntrinsicInst>(I))
4412 if (cast<llvm::CallBase>(I).doesNotThrow())
4420 Builder.SetInsertPoint(&BB, BI);
4421 emitReadHazard(Builder);
4428 if (llvm::Value *Ptr =
V.getBasePointer())
4432void FragileHazards::collectLocals() {
4434 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
4440 llvm::BasicBlock &Entry = CGF.
CurFn->getEntryBlock();
4441 for (llvm::BasicBlock::iterator
4442 I = Entry.begin(),
E = Entry.end(); I !=
E; ++I)
4443 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
4444 Locals.push_back(&*I);
4447llvm::FunctionType *FragileHazards::GetAsmFnType() {
4449 for (
unsigned i = 0, e = Locals.size(); i != e; ++i)
4450 tys[i] = Locals[i]->getType();
4451 return llvm::FunctionType::get(CGF.
VoidTy, tys,
false);
4564 bool isTry = isa<ObjCAtTryStmt>(S);
4568 CodeGenFunction::JumpDest FinallyEnd =
4573 CodeGenFunction::JumpDest FinallyRethrow =
4583 llvm::Value *SyncArg =
4584 CGF.
EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
4585 SyncArg = CGF.
Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
4597 "exceptiondata.ptr");
4603 FragileHazards Hazards(CGF);
4632 ExceptionData.emitRawPointer(CGF));
4635 llvm::Constant *
Zero = llvm::ConstantInt::get(CGF.
Builder.getInt32Ty(), 0);
4638 ObjCTypes.ExceptionDataTy, ExceptionData.emitRawPointer(CGF), GEPIndexes,
4641 ObjCTypes.getSetJmpFn(), SetJmpBuffer,
"setjmp_result");
4642 SetJmpResult->setCanReturnTwice();
4648 llvm::Value *DidCatch =
4649 CGF.
Builder.CreateIsNotNull(SetJmpResult,
"did_catch_exception");
4650 CGF.
Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
4655 CGF.
EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
4656 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
4658 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.
Builder.saveAndClearIP();
4664 Hazards.emitWriteHazard();
4668 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
4678 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF),
4689 llvm::BasicBlock *CatchBlock =
nullptr;
4690 llvm::BasicBlock *CatchHandler =
nullptr;
4696 "propagating_exception");
4702 ExceptionData.emitRawPointer(CGF));
4704 llvm::CallInst *SetJmpResult =
4706 SetJmpBuffer,
"setjmp.result");
4707 SetJmpResult->setCanReturnTwice();
4709 llvm::Value *Threw =
4710 CGF.
Builder.CreateIsNotNull(SetJmpResult,
"did_catch_exception");
4714 CGF.
Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
4724 bool AllMatched =
false;
4726 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
4745 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4752 EmitInitOfCatchParam(CGF, Caught, CatchParam);
4755 CGF.
EmitStmt(CatchStmt->getCatchBody());
4758 CatchVarCleanups.ForceCleanup();
4764 assert(OPT &&
"Unexpected non-object pointer type in @catch");
4769 assert(IDecl &&
"Catch parameter must have Objective-C type!");
4772 llvm::Value *
Class = EmitClassRef(CGF, IDecl);
4774 llvm::Value *matchArgs[] = {
Class, Caught };
4775 llvm::CallInst *Match =
4777 matchArgs,
"match");
4782 CGF.
Builder.CreateCondBr(CGF.
Builder.CreateIsNotNull(Match,
"matched"),
4783 MatchedBlock, NextCatchBlock);
4790 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4797 CGF.
Builder.CreateBitCast(Caught,
4799 EmitInitOfCatchParam(CGF, Tmp, CatchParam);
4801 CGF.
EmitStmt(CatchStmt->getCatchBody());
4804 CatchVarCleanups.ForceCleanup();
4815 if (Caught->use_empty())
4816 Caught->eraseFromParent();
4832 assert(PropagatingExnVar.
isValid());
4834 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF),
4845 Hazards.emitHazardsInNewBlocks();
4848 CGF.
Builder.restoreIP(TryFallthroughIP);
4852 CGF.
EmitBlock(FinallyEnd.getBlock(),
true);
4855 CGBuilderTy::InsertPoint SavedIP = CGF.
Builder.saveAndClearIP();
4856 CGF.
EmitBlock(FinallyRethrow.getBlock(),
true);
4859 llvm::Value *PropagatingExn;
4860 if (PropagatingExnVar.
isValid()) {
4866 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF));
4867 PropagatingExn = Caught;
4872 CGF.
Builder.CreateUnreachable();
4875 CGF.
Builder.restoreIP(SavedIP);
4880 bool ClearInsertionPoint) {
4881 llvm::Value *ExceptionAsObject;
4883 if (
const Expr *ThrowExpr = S.getThrowExpr()) {
4886 CGF.
Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
4889 "Unexpected rethrow outside @catch block.");
4893 CGF.
EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
4894 ->setDoesNotReturn();
4895 CGF.
Builder.CreateUnreachable();
4898 if (ClearInsertionPoint)
4899 CGF.
Builder.ClearInsertionPoint();
4908 llvm::Value *AddrWeakObjVal = CGF.
Builder.CreateBitCast(
4910 llvm::Value *read_weak =
4912 AddrWeakObjVal,
"weakread");
4913 read_weak = CGF.
Builder.CreateBitCast(read_weak, DestTy);
4921 llvm::Value *src,
Address dst) {
4922 llvm::Type * SrcTy = src->getType();
4923 if (!isa<llvm::PointerType>(SrcTy)) {
4925 assert(Size <= 8 && "does not support size > 8
");
4926 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4927 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4928 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4930 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4931 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4932 ObjCTypes.PtrObjectPtrTy);
4933 llvm::Value *args[] = { src, dstVal };
4934 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
4935 args, "weakassign
");
4941void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
4942 llvm::Value *src, Address dst,
4944 llvm::Type * SrcTy = src->getType();
4945 if (!isa<llvm::PointerType>(SrcTy)) {
4946 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4947 assert(Size <= 8 && "does
not support size > 8
");
4948 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4949 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4950 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4952 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4953 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4954 ObjCTypes.PtrObjectPtrTy);
4955 llvm::Value *args[] = {src, dstVal};
4957 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
4958 args, "globalassign
");
4960 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
4961 args, "threadlocalassign
");
4967void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
4968 llvm::Value *src, Address dst,
4969 llvm::Value *ivarOffset) {
4970 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is
NULL");
4971 llvm::Type * SrcTy = src->getType();
4972 if (!isa<llvm::PointerType>(SrcTy)) {
4973 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4974 assert(Size <= 8 && "does
not support size > 8
");
4975 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4976 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4977 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4979 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4980 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4981 ObjCTypes.PtrObjectPtrTy);
4982 llvm::Value *args[] = {src, dstVal, ivarOffset};
4983 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
4989void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
4990 llvm::Value *src, Address dst) {
4991 llvm::Type * SrcTy = src->getType();
4992 if (!isa<llvm::PointerType>(SrcTy)) {
4993 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4994 assert(Size <= 8 && "does
not support size > 8
");
4995 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4996 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4997 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4999 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5000 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
5001 ObjCTypes.PtrObjectPtrTy);
5002 llvm::Value *args[] = {src, dstVal};
5003 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
5004 args, "strongassign
");
5007void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
5008 Address DestPtr, Address SrcPtr,
5009 llvm::Value *size) {
5010 llvm::Value *args[] = {DestPtr.emitRawPointer(CGF),
5011 SrcPtr.emitRawPointer(CGF), size};
5012 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
5017LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
5019 llvm::Value *BaseValue,
5020 const ObjCIvarDecl *Ivar,
5021 unsigned CVRQualifiers) {
5022 const ObjCInterfaceDecl *ID =
5023 ObjectTy->castAs<ObjCObjectType>()->getInterface();
5024 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5025 EmitIvarOffset(CGF, ID, Ivar));
5028llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
5029 const ObjCInterfaceDecl *Interface,
5030 const ObjCIvarDecl *Ivar) {
5031 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
5032 return llvm::ConstantInt::get(
5033 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
5037/* *** Private Interface *** */
5039std::string CGObjCCommonMac::GetSectionName(StringRef Section,
5040 StringRef MachOAttributes) {
5041 switch (CGM.getTriple().getObjectFormat()) {
5042 case llvm::Triple::UnknownObjectFormat:
5043 llvm_unreachable("unexpected
object file format
");
5044 case llvm::Triple::MachO: {
5045 if (MachOAttributes.empty())
5046 return ("__DATA,
" + Section).str();
5047 return ("__DATA,
" + Section + ",
" + MachOAttributes).str();
5049 case llvm::Triple::ELF:
5050 assert(Section.starts_with("__
") && "expected the name to begin with __
");
5051 return Section.substr(2).str();
5052 case llvm::Triple::COFF:
5053 assert(Section.starts_with("__
") && "expected the name to begin with __
");
5054 return (".
" + Section.substr(2) + "$B
").str();
5055 case llvm::Triple::Wasm:
5056 case llvm::Triple::GOFF:
5057 case llvm::Triple::SPIRV:
5058 case llvm::Triple::XCOFF:
5059 case llvm::Triple::DXContainer:
5060 llvm::report_fatal_error(
5061 "Objective-
C support is unimplemented
for object file format
");
5064 llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType
enum");
5075enum ImageInfoFlags {
5076 eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
5077 eImageInfo_GarbageCollected = (1 << 1),
5078 eImageInfo_GCOnly = (1 << 2),
5079 eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
5081 // A flag indicating that the module has no instances of a @synthesize of a
5082 // superclass variable. This flag used to be consumed by the runtime to work
5083 // around miscompile by gcc.
5084 eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang.
5085 eImageInfo_ImageIsSimulated = (1 << 5),
5086 eImageInfo_ClassProperties = (1 << 6)
5089void CGObjCCommonMac::EmitImageInfo() {
5090 unsigned version = 0; // Version is unused?
5091 std::string Section =
5093 ? "__OBJC,__image_info,regular
"
5094 : GetSectionName("__objc_imageinfo
", "regular,no_dead_strip
");
5096 // Generate module-level named metadata to convey this information to the
5097 // linker and code-gen.
5098 llvm::Module &Mod = CGM.getModule();
5100 // Add the ObjC ABI version to the module flags.
5101 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Version
", ObjCABI);
5102 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Image Info Version
",
5104 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Image Info Section
",
5105 llvm::MDString::get(VMContext, Section));
5107 auto Int8Ty = llvm::Type::getInt8Ty(VMContext);
5108 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
5109 // Non-GC overrides those files which specify GC.
5110 Mod.addModuleFlag(llvm::Module::Error,
5111 "Objective-
C Garbage Collection
",
5112 llvm::ConstantInt::get(Int8Ty,0));
5114 // Add the ObjC garbage collection value.
5115 Mod.addModuleFlag(llvm::Module::Error,
5116 "Objective-
C Garbage Collection
",
5117 llvm::ConstantInt::get(Int8Ty,
5118 (uint8_t)eImageInfo_GarbageCollected));
5120 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
5121 // Add the ObjC GC Only value.
5122 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C GC Only
",
5125 // Require that GC be specified and set to eImageInfo_GarbageCollected.
5126 llvm::Metadata *Ops[2] = {
5127 llvm::MDString::get(VMContext, "Objective-
C Garbage Collection
"),
5128 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
5129 Int8Ty, eImageInfo_GarbageCollected))};
5130 Mod.addModuleFlag(llvm::Module::Require, "Objective-
C GC Only
",
5131 llvm::MDNode::get(VMContext, Ops));
5135 // Indicate whether we're compiling this to run on a simulator.
5136 if (CGM.getTarget().getTriple().isSimulatorEnvironment())
5137 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Is Simulated
",
5138 eImageInfo_ImageIsSimulated);
5140 // Indicate whether we are generating class properties.
5141 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Class Properties
",
5142 eImageInfo_ClassProperties);
5145// struct objc_module {
5146// unsigned long version;
5147// unsigned long size;
5152// FIXME: Get from somewhere
5153static const int ModuleVersion = 7;
5155void CGObjCMac::EmitModuleInfo() {
5156 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
5158 ConstantInitBuilder builder(CGM);
5159 auto values = builder.beginStruct(ObjCTypes.ModuleTy);
5160 values.addInt(ObjCTypes.LongTy, ModuleVersion);
5161 values.addInt(ObjCTypes.LongTy, Size);
5162 // This used to be the filename, now it is unused. <rdr://4327263>
5163 values.add(GetClassName(StringRef("")));
5164 values.add(EmitModuleSymbols());
5165 CreateMetadataVar("OBJC_MODULES
", values,
5166 "__OBJC,__module_info,regular,no_dead_strip
",
5167 CGM.getPointerAlign(), true);
5170llvm::Constant *CGObjCMac::EmitModuleSymbols() {
5171 unsigned NumClasses = DefinedClasses.size();
5172 unsigned NumCategories = DefinedCategories.size();
5174 // Return null if no symbols were defined.
5175 if (!NumClasses && !NumCategories)
5176 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
5178 ConstantInitBuilder builder(CGM);
5179 auto values = builder.beginStruct();
5180 values.addInt(ObjCTypes.LongTy, 0);
5181 values.addNullPointer(ObjCTypes.SelectorPtrTy);
5182 values.addInt(ObjCTypes.ShortTy, NumClasses);
5183 values.addInt(ObjCTypes.ShortTy, NumCategories);
5185 // The runtime expects exactly the list of defined classes followed
5186 // by the list of defined categories, in a single array.
5187 auto array = values.beginArray(ObjCTypes.Int8PtrTy);
5188 for (unsigned i=0; i<NumClasses; i++) {
5189 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
5191 if (ObjCImplementationDecl *IMP = ID->getImplementation())
5192 // We are implementing a weak imported interface. Give it external linkage
5193 if (ID->isWeakImported() && !IMP->isWeakImported())
5194 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
5196 array.add(DefinedClasses[i]);
5198 for (unsigned i=0; i<NumCategories; i++)
5199 array.add(DefinedCategories[i]);
5201 array.finishAndAddTo(values);
5203 llvm::GlobalVariable *GV = CreateMetadataVar(
5204 "OBJC_SYMBOLS
", values, "__OBJC,__symbols,regular,no_dead_strip
",
5205 CGM.getPointerAlign(), true);
5209llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
5210 IdentifierInfo *II) {
5211 LazySymbols.insert(II);
5213 llvm::GlobalVariable *&Entry = ClassReferences[II];
5217 CreateMetadataVar("OBJC_CLASS_REFERENCES_
", GetClassName(II->getName()),
5218 "__OBJC,__cls_refs,literal_pointers,no_dead_strip
",
5219 CGM.getPointerAlign(), true);
5222 return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry,
5223 CGF.getPointerAlign());
5226llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
5227 const ObjCInterfaceDecl *ID) {
5228 // If the class has the objc_runtime_visible attribute, we need to
5229 // use the Objective-C runtime to get the class.
5230 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
5231 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
5233 IdentifierInfo *RuntimeName =
5234 &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
5235 return EmitClassRefFromId(CGF, RuntimeName);
5238llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
5239 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool
");
5240 return EmitClassRefFromId(CGF, II);
5243llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
5244 return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel));
5247ConstantAddress CGObjCMac::EmitSelectorAddr(Selector Sel) {
5248 CharUnits Align = CGM.getPointerAlign();
5250 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
5252 Entry = CreateMetadataVar(
5253 "OBJC_SELECTOR_REFERENCES_
", GetMethodVarName(Sel),
5254 "__OBJC,__message_refs,literal_pointers,no_dead_strip
", Align, true);
5255 Entry->setExternallyInitialized(true);
5258 return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align);
5261llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
5262 llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
5264 Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
5265 return getConstantGEP(VMContext, Entry, 0, 0);
5268llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
5269 return MethodDefinitions.lookup(MD);
5274llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
5275 const ObjCCommonTypesHelper &ObjCTypes) {
5276 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
5279void IvarLayoutBuilder::visitRecord(const RecordType *RT,
5281 const RecordDecl *RD = RT->getDecl();
5283 // If this is a union, remember that we had one, because it might mess
5284 // up the ordering of layout entries.
5286 IsDisordered = true;
5288 const ASTRecordLayout *recLayout = nullptr;
5289 visitAggregate(RD->field_begin(), RD->field_end(), offset,
5290 [&](const FieldDecl *field) -> CharUnits {
5292 recLayout = &CGM.getContext().getASTRecordLayout(RD);
5293 auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex());
5294 return CGM.getContext().toCharUnitsFromBits(offsetInBits);
5298template <class Iterator, class GetOffsetFn>
5299void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
5300 CharUnits aggregateOffset,
5301 const GetOffsetFn &getOffset) {
5302 for (; begin != end; ++begin) {
5303 auto field = *begin;
5305 // Skip over bitfields.
5306 if (field->isBitField()) {
5310 // Compute the offset of the field within the aggregate.
5311 CharUnits fieldOffset = aggregateOffset + getOffset(field);
5313 visitField(field, fieldOffset);
5318void IvarLayoutBuilder::visitField(const FieldDecl *field,
5319 CharUnits fieldOffset) {
5320 QualType fieldType = field->getType();
5322 // Drill down into arrays.
5323 uint64_t numElts = 1;
5324 if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) {
5326 fieldType = arrayType->getElementType();
5328 // Unlike incomplete arrays, constant arrays can be nested.
5329 while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
5330 numElts *= arrayType->getZExtSize();
5331 fieldType = arrayType->getElementType();
5334 assert(!fieldType->isArrayType() && "ivar of non-constant array
type?
");
5336 // If we ended up with a zero-sized array, we've done what we can do within
5337 // the limits of this layout encoding.
5338 if (numElts == 0) return;
5340 // Recurse if the base element type is a record type.
5341 if (auto recType = fieldType->getAs<RecordType>()) {
5342 size_t oldEnd = IvarsInfo.size();
5344 visitRecord(recType, fieldOffset);
5346 // If we have an array, replicate the first entry's layout information.
5347 auto numEltEntries = IvarsInfo.size() - oldEnd;
5348 if (numElts != 1 && numEltEntries != 0) {
5349 CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
5350 for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
5351 // Copy the last numEltEntries onto the end of the array, adjusting
5352 // each for the element size.
5353 for (size_t i = 0; i != numEltEntries; ++i) {
5354 auto firstEntry = IvarsInfo[oldEnd + i];
5355 IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
5356 firstEntry.SizeInWords));
5364 // Classify the element type.
5365 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
5367 // If it matches what we're looking for, add an entry.
5368 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
5369 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
5370 assert(CGM.getContext().getTypeSizeInChars(fieldType)
5371 == CGM.getPointerSize());
5372 IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
5379llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
5380 llvm::SmallVectorImpl<unsigned char> &buffer) {
5381 // The bitmap is a series of skip/scan instructions, aligned to word
5382 // boundaries. The skip is performed first.
5383 const unsigned char MaxNibble = 0xF;
5384 const unsigned char SkipMask = 0xF0, SkipShift = 4;
5385 const unsigned char ScanMask = 0x0F, ScanShift = 0;
5387 assert(!IvarsInfo.empty() && "generating bitmap
for no data
");
5389 // Sort the ivar info on byte position in case we encounterred a
5390 // union nested in the ivar list.
5392 // This isn't a stable sort, but our algorithm should handle it fine.
5393 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
5395 assert(llvm::is_sorted(IvarsInfo));
5397 assert(IvarsInfo.back().Offset < InstanceEnd);
5399 assert(buffer.empty());
5401 // Skip the next N words.
5402 auto skip = [&](unsigned numWords) {
5403 assert(numWords > 0);
5405 // Try to merge into the previous byte. Since scans happen second, we
5406 // can't do this if it includes a scan.
5407 if (!buffer.empty() && !(buffer.back() & ScanMask)) {
5408 unsigned lastSkip = buffer.back() >> SkipShift;
5409 if (lastSkip < MaxNibble) {
5410 unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
5411 numWords -= claimed;
5412 lastSkip += claimed;
5413 buffer.back() = (lastSkip << SkipShift);
5417 while (numWords >= MaxNibble) {
5418 buffer.push_back(MaxNibble << SkipShift);
5419 numWords -= MaxNibble;
5422 buffer.push_back(numWords << SkipShift);
5426 // Scan the next N words.
5427 auto scan = [&](unsigned numWords) {
5428 assert(numWords > 0);
5430 // Try to merge into the previous byte. Since scans happen second, we can
5431 // do this even if it includes a skip.
5432 if (!buffer.empty()) {
5433 unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
5434 if (lastScan < MaxNibble) {
5435 unsigned claimed = std::min(MaxNibble - lastScan, numWords);
5436 numWords -= claimed;
5437 lastScan += claimed;
5438 buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
5442 while (numWords >= MaxNibble) {
5443 buffer.push_back(MaxNibble << ScanShift);
5444 numWords -= MaxNibble;
5447 buffer.push_back(numWords << ScanShift);
5451 // One past the end of the last scan.
5452 unsigned endOfLastScanInWords = 0;
5453 const CharUnits WordSize = CGM.getPointerSize();
5455 // Consider all the scan requests.
5456 for (auto &request : IvarsInfo) {
5457 CharUnits beginOfScan = request.Offset - InstanceBegin;
5459 // Ignore scan requests that don't start at an even multiple of the
5460 // word size. We can't encode them.
5461 if ((beginOfScan % WordSize) != 0) continue;
5463 // Ignore scan requests that start before the instance start.
5464 // This assumes that scans never span that boundary. The boundary
5465 // isn't the true start of the ivars, because in the fragile-ARC case
5466 // it's rounded up to word alignment, but the test above should leave
5467 // us ignoring that possibility.
5468 if (beginOfScan.isNegative()) {
5469 assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
5473 unsigned beginOfScanInWords = beginOfScan / WordSize;
5474 unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
5476 // If the scan starts some number of words after the last one ended,
5478 if (beginOfScanInWords > endOfLastScanInWords) {
5479 skip(beginOfScanInWords - endOfLastScanInWords);
5481 // Otherwise, start scanning where the last left off.
5483 beginOfScanInWords = endOfLastScanInWords;
5485 // If that leaves us with nothing to scan, ignore this request.
5486 if (beginOfScanInWords >= endOfScanInWords) continue;
5489 // Scan to the end of the request.
5490 assert(beginOfScanInWords < endOfScanInWords);
5491 scan(endOfScanInWords - beginOfScanInWords);
5492 endOfLastScanInWords = endOfScanInWords;
5496 return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
5498 // For GC layouts, emit a skip to the end of the allocation so that we
5499 // have precise information about the entire thing. This isn't useful
5500 // or necessary for the ARC-style layout strings.
5501 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
5502 unsigned lastOffsetInWords =
5503 (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
5504 if (lastOffsetInWords > endOfLastScanInWords) {
5505 skip(lastOffsetInWords - endOfLastScanInWords);
5509 // Null terminate the string.
5510 buffer.push_back(0);
5512 auto *Entry = CGObjC.CreateCStringLiteral(
5513 reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName);
5514 return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
5534CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
5535 CharUnits beginOffset, CharUnits endOffset,
5536 bool ForStrongLayout, bool HasMRCWeakIvars) {
5537 // If this is MRC, and we're either building a strong layout or there
5538 // are no weak ivars, bail out early.
5539 llvm::Type *PtrTy = CGM.Int8PtrTy;
5540 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
5541 !CGM.getLangOpts().ObjCAutoRefCount &&
5542 (ForStrongLayout || !HasMRCWeakIvars))
5543 return llvm::Constant::getNullValue(PtrTy);
5545 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
5546 SmallVector<const ObjCIvarDecl*, 32> ivars;
5548 // GC layout strings include the complete object layout, possibly
5549 // inaccurately in the non-fragile ABI; the runtime knows how to fix this
5552 // ARC layout strings only include the class's ivars. In non-fragile
5553 // runtimes, that means starting at InstanceStart, rounded up to word
5554 // alignment. In fragile runtimes, there's no InstanceStart, so it means
5555 // starting at the offset of the first ivar, rounded up to word alignment.
5557 // MRC weak layout strings follow the ARC style.
5558 CharUnits baseOffset;
5559 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
5560 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
5561 IVD; IVD = IVD->getNextIvar())
5562 ivars.push_back(IVD);
5564 if (isNonFragileABI()) {
5565 baseOffset = beginOffset; // InstanceStart
5566 } else if (!ivars.empty()) {
5568 CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
5570 baseOffset = CharUnits::Zero();
5573 baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
5576 CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
5578 baseOffset = CharUnits::Zero();
5582 return llvm::Constant::getNullValue(PtrTy);
5584 IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
5586 builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
5587 [&](const ObjCIvarDecl *ivar) -> CharUnits {
5588 return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar));
5591 if (!builder.hasBitmapData())
5592 return llvm::Constant::getNullValue(PtrTy);
5594 llvm::SmallVector<unsigned char, 4> buffer;
5595 llvm::Constant *C = builder.buildBitmap(*this, buffer);
5597 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
5598 printf("\n%
s ivar layout
for class '%s':
",
5599 ForStrongLayout ? "strong
" : "weak
",
5600 OMD->getClassInterface()->getName().str().c_str());
5601 builder.dump(buffer);
5606llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
5607 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
5608 // FIXME: Avoid std::string in "Sel.
getAsString()
"
5610 Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
5611 return getConstantGEP(VMContext, Entry, 0, 0);
5614// FIXME: Merge into a single cstring creation function.
5615llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
5616 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
5619llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
5620 std::string TypeStr;
5621 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
5623 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
5625 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
5626 return getConstantGEP(VMContext, Entry, 0, 0);
5629llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
5631 std::string TypeStr =
5632 CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
5634 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
5636 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
5637 return getConstantGEP(VMContext, Entry, 0, 0);
5640// FIXME: Merge into a single cstring creation function.
5641llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
5642 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
5644 Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
5645 return getConstantGEP(VMContext, Entry, 0, 0);
5648// FIXME: Merge into a single cstring creation function.
5649// FIXME: This Decl should be more precise.
5651CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
5652 const Decl *Container) {
5653 std::string TypeStr =
5654 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
5655 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
5658void CGObjCMac::FinishModule() {
5661 // Emit the dummy bodies for any protocols which were referenced but
5663 for (auto &entry : Protocols) {
5664 llvm::GlobalVariable *global = entry.second;
5665 if (global->hasInitializer())
5668 ConstantInitBuilder builder(CGM);
5669 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
5670 values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
5671 values.add(GetClassName(entry.first->getName()));
5672 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
5673 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5674 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5675 values.finishAndSetAsInitializer(global);
5676 CGM.addCompilerUsedGlobal(global);
5679 // Add assembler directives to add lazy undefined symbol references
5680 // for classes which are referenced but not defined. This is
5681 // important for correct linker interaction.
5683 // FIXME: It would be nice if we had an LLVM construct for this.
5684 if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
5685 CGM.getTriple().isOSBinFormatMachO()) {
5686 SmallString<256> Asm;
5687 Asm += CGM.getModule().getModuleInlineAsm();
5688 if (!Asm.empty() && Asm.back() != '\n')
5691 llvm::raw_svector_ostream OS(Asm);
5692 for (const auto *Sym : DefinedSymbols)
5693 OS << "\t.objc_class_name_
" << Sym->getName() << "=0\n
"
5694 << "\t.globl .objc_class_name_
" << Sym->getName() << "\n
";
5695 for (const auto *Sym : LazySymbols)
5696 OS << "\t.lazy_reference .objc_class_name_
" << Sym->getName() << "\n
";
5697 for (const auto &Category : DefinedCategoryNames)
5698 OS << "\t.objc_category_name_
" << Category << "=0\n
"
5699 << "\t.globl .objc_category_name_
" << Category << "\n
";
5701 CGM.getModule().setModuleInlineAsm(OS.str());
5705CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
5706 : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
5707 ObjCEmptyVtableVar(nullptr) {
5713ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
5714 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr)
5716 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5717 ASTContext &Ctx = CGM.getContext();
5718 unsigned ProgramAS = CGM.getDataLayout().getProgramAddressSpace();
5720 ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
5722 LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
5723 Int8PtrTy = CGM.Int8PtrTy;
5724 Int8PtrProgramASTy = llvm::PointerType::get(CGM.Int8Ty, ProgramAS);
5725 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
5727 // arm64 targets use "int" ivar offset variables. All others,
5728 // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
5729 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
5730 IvarOffsetVarTy = IntTy;
5732 IvarOffsetVarTy = LongTy;
5735 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
5737 llvm::PointerType::getUnqual(ObjectPtrTy);
5739 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
5741 // I'm not sure I like this. The implicit coordination is a bit
5742 // gross. We should solve this in a reasonable fashion because this
5743 // is a pretty common task (match some runtime data structure with
5744 // an LLVM data structure).
5746 // FIXME: This is leaked.
5747 // FIXME: Merge with rewriter code?
5749 // struct _objc_super {
5753 RecordDecl *RD = RecordDecl::Create(
5754 Ctx, TagTypeKind::Struct, Ctx.getTranslationUnitDecl(), SourceLocation(),
5755 SourceLocation(), &Ctx.Idents.get("_objc_super
"));
5756 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5757 nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
5758 false, ICIS_NoInit));
5759 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5760 nullptr, Ctx.getObjCClassType(), nullptr,
5761 nullptr, false, ICIS_NoInit));
5762 RD->completeDefinition();
5764 SuperCTy = Ctx.getTagDeclType(RD);
5765 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
5767 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
5768 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
5772 // char *attributes;
5774 PropertyTy = llvm::StructType::create("struct._prop_t
", Int8PtrTy, Int8PtrTy);
5776 // struct _prop_list_t {
5777 // uint32_t entsize; // sizeof(struct _prop_t)
5778 // uint32_t count_of_properties;
5779 // struct _prop_t prop_list[count_of_properties];
5781 PropertyListTy = llvm::StructType::create(
5782 "struct._prop_list_t
", IntTy, IntTy, llvm::ArrayType::get(PropertyTy, 0));
5783 // struct _prop_list_t *
5784 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
5786 // struct _objc_method {
5788 // char *method_type;
5791 MethodTy = llvm::StructType::create("struct._objc_method
", SelectorPtrTy,
5792 Int8PtrTy, Int8PtrProgramASTy);
5794 // struct _objc_cache *
5795 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache
");
5796 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
5799ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
5800 : ObjCCommonTypesHelper(cgm) {
5801 // struct _objc_method_description {
5805 MethodDescriptionTy = llvm::StructType::create(
5806 "struct._objc_method_description
", SelectorPtrTy, Int8PtrTy);
5808 // struct _objc_method_description_list {
5810 // struct _objc_method_description[1];
5812 MethodDescriptionListTy =
5813 llvm::StructType::create("struct._objc_method_description_list
", IntTy,
5814 llvm::ArrayType::get(MethodDescriptionTy, 0));
5816 // struct _objc_method_description_list *
5817 MethodDescriptionListPtrTy =
5818 llvm::PointerType::getUnqual(MethodDescriptionListTy);
5820 // Protocol description structures
5822 // struct _objc_protocol_extension {
5823 // uint32_t size; // sizeof(struct _objc_protocol_extension)
5824 // struct _objc_method_description_list *optional_instance_methods;
5825 // struct _objc_method_description_list *optional_class_methods;
5826 // struct _objc_property_list *instance_properties;
5827 // const char ** extendedMethodTypes;
5828 // struct _objc_property_list *class_properties;
5830 ProtocolExtensionTy = llvm::StructType::create(
5831 "struct._objc_protocol_extension
", IntTy, MethodDescriptionListPtrTy,
5832 MethodDescriptionListPtrTy, PropertyListPtrTy, Int8PtrPtrTy,
5835 // struct _objc_protocol_extension *
5836 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
5838 // Handle recursive construction of Protocol and ProtocolList types
5841 llvm::StructType::create(VMContext, "struct._objc_protocol
");
5844 llvm::StructType::create(VMContext, "struct._objc_protocol_list
");
5845 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy), LongTy,
5846 llvm::ArrayType::get(ProtocolTy, 0));
5848 // struct _objc_protocol {
5849 // struct _objc_protocol_extension *isa;
5850 // char *protocol_name;
5851 // struct _objc_protocol **_objc_protocol_list;
5852 // struct _objc_method_description_list *instance_methods;
5853 // struct _objc_method_description_list *class_methods;
5855 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
5856 llvm::PointerType::getUnqual(ProtocolListTy),
5857 MethodDescriptionListPtrTy, MethodDescriptionListPtrTy);
5859 // struct _objc_protocol_list *
5860 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
5862 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
5864 // Class description structures
5866 // struct _objc_ivar {
5871 IvarTy = llvm::StructType::create("struct._objc_ivar
", Int8PtrTy, Int8PtrTy,
5874 // struct _objc_ivar_list *
5876 llvm::StructType::create(VMContext, "struct._objc_ivar_list
");
5877 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
5879 // struct _objc_method_list *
5881 llvm::StructType::create(VMContext, "struct._objc_method_list
");
5882 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
5884 // struct _objc_class_extension *
5885 ClassExtensionTy = llvm::StructType::create(
5886 "struct._objc_class_extension
", IntTy, Int8PtrTy, PropertyListPtrTy);
5887 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
5889 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class
");
5891 // struct _objc_class {
5893 // Class super_class;
5897 // long instance_size;
5898 // struct _objc_ivar_list *ivars;
5899 // struct _objc_method_list *methods;
5900 // struct _objc_cache *cache;
5901 // struct _objc_protocol_list *protocols;
5902 // char *ivar_layout;
5903 // struct _objc_class_ext *ext;
5905 ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
5906 llvm::PointerType::getUnqual(ClassTy), Int8PtrTy, LongTy,
5907 LongTy, LongTy, IvarListPtrTy, MethodListPtrTy, CachePtrTy,
5908 ProtocolListPtrTy, Int8PtrTy, ClassExtensionPtrTy);
5910 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
5912 // struct _objc_category {
5913 // char *category_name;
5914 // char *class_name;
5915 // struct _objc_method_list *instance_method;
5916 // struct _objc_method_list *class_method;
5917 // struct _objc_protocol_list *protocols;
5918 // uint32_t size; // sizeof(struct _objc_category)
5919 // struct _objc_property_list *instance_properties;// category's @property
5920 // struct _objc_property_list *class_properties;
5922 CategoryTy = llvm::StructType::create(
5923 "struct._objc_category
", Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5924 MethodListPtrTy, ProtocolListPtrTy, IntTy, PropertyListPtrTy,
5927 // Global metadata structures
5929 // struct _objc_symtab {
5930 // long sel_ref_cnt;
5932 // short cls_def_cnt;
5933 // short cat_def_cnt;
5934 // char *defs[cls_def_cnt + cat_def_cnt];
5936 SymtabTy = llvm::StructType::create("struct._objc_symtab
", LongTy,
5937 SelectorPtrTy, ShortTy, ShortTy,
5938 llvm::ArrayType::get(Int8PtrTy, 0));
5939 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
5941 // struct _objc_module {
5943 // long size; // sizeof(struct _objc_module)
5945 // struct _objc_symtab* symtab;
5947 ModuleTy = llvm::StructType::create("struct._objc_module
", LongTy, LongTy,
5948 Int8PtrTy, SymtabPtrTy);
5950 // FIXME: This is the size of the setjmp buffer and should be target
5951 // specific. 18 is what's used on 32-bit X86.
5952 uint64_t SetJmpBufferSize = 18;
5955 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
5957 ExceptionDataTy = llvm::StructType::create(
5958 "struct._objc_exception_data
",
5959 llvm::ArrayType::get(CGM.Int32Ty, SetJmpBufferSize), StackPtrTy);
5962ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
5963 : ObjCCommonTypesHelper(cgm) {
5964 // struct _method_list_t {
5965 // uint32_t entsize; // sizeof(struct _objc_method)
5966 // uint32_t method_count;
5967 // struct _objc_method method_list[method_count];
5970 llvm::StructType::create("struct.__method_list_t
", IntTy, IntTy,
5971 llvm::ArrayType::get(MethodTy, 0));
5972 // struct method_list_t *
5973 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
5975 // struct _protocol_t {
5977 // const char * const protocol_name;
5978 // const struct _protocol_list_t * protocol_list; // super protocols
5979 // const struct method_list_t * const instance_methods;
5980 // const struct method_list_t * const class_methods;
5981 // const struct method_list_t *optionalInstanceMethods;
5982 // const struct method_list_t *optionalClassMethods;
5983 // const struct _prop_list_t * properties;
5984 // const uint32_t size; // sizeof(struct _protocol_t)
5985 // const uint32_t flags; // = 0
5986 // const char ** extendedMethodTypes;
5987 // const char *demangledName;
5988 // const struct _prop_list_t * class_properties;
5991 // Holder for struct _protocol_list_t *
5992 ProtocolListnfABITy =
5993 llvm::StructType::create(VMContext, "struct._objc_protocol_list
");
5995 ProtocolnfABITy = llvm::StructType::create(
5996 "struct._protocol_t
", ObjectPtrTy, Int8PtrTy,
5997 llvm::PointerType::getUnqual(ProtocolListnfABITy), MethodListnfABIPtrTy,
5998 MethodListnfABIPtrTy, MethodListnfABIPtrTy, MethodListnfABIPtrTy,
5999 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy, Int8PtrTy,
6002 // struct _protocol_t*
6003 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
6005 // struct _protocol_list_t {
6006 // long protocol_count; // Note, this is 32/64 bit
6007 // struct _protocol_t *[protocol_count];
6009 ProtocolListnfABITy->setBody(LongTy,
6010 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0));
6012 // struct _objc_protocol_list*
6013 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
6016 // unsigned [long] int *offset; // pointer to ivar offset location
6019 // uint32_t alignment;
6022 IvarnfABITy = llvm::StructType::create(
6023 "struct._ivar_t
", llvm::PointerType::getUnqual(IvarOffsetVarTy),
6024 Int8PtrTy, Int8PtrTy, IntTy, IntTy);
6026 // struct _ivar_list_t {
6027 // uint32 entsize; // sizeof(struct _ivar_t)
6029 // struct _iver_t list[count];
6032 llvm::StructType::create("struct._ivar_list_t
", IntTy, IntTy,
6033 llvm::ArrayType::get(IvarnfABITy, 0));
6035 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
6037 // struct _class_ro_t {
6038 // uint32_t const flags;
6039 // uint32_t const instanceStart;
6040 // uint32_t const instanceSize;
6041 // uint32_t const reserved; // only when building for 64bit targets
6042 // const uint8_t * const ivarLayout;
6043 // const char *const name;
6044 // const struct _method_list_t * const baseMethods;
6045 // const struct _objc_protocol_list *const baseProtocols;
6046 // const struct _ivar_list_t *const ivars;
6047 // const uint8_t * const weakIvarLayout;
6048 // const struct _prop_list_t * const properties;
6051 // FIXME. Add 'reserved' field in 64bit abi mode!
6052 ClassRonfABITy = llvm::StructType::create(
6053 "struct._class_ro_t
", IntTy, IntTy, IntTy, Int8PtrTy, Int8PtrTy,
6054 MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, IvarListnfABIPtrTy,
6055 Int8PtrTy, PropertyListPtrTy);
6057 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
6058 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
6059 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
6062 // struct _class_t {
6063 // struct _class_t *isa;
6064 // struct _class_t * const superclass;
6067 // struct class_ro_t *ro;
6070 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t
");
6071 ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
6072 llvm::PointerType::getUnqual(ClassnfABITy), CachePtrTy,
6073 llvm::PointerType::getUnqual(ImpnfABITy),
6074 llvm::PointerType::getUnqual(ClassRonfABITy));
6076 // LLVM for struct _class_t *
6077 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
6079 // struct _category_t {
6080 // const char * const name;
6081 // struct _class_t *const cls;
6082 // const struct _method_list_t * const instance_methods;
6083 // const struct _method_list_t * const class_methods;
6084 // const struct _protocol_list_t * const protocols;
6085 // const struct _prop_list_t * const properties;
6086 // const struct _prop_list_t * const class_properties;
6087 // const uint32_t size;
6089 CategorynfABITy = llvm::StructType::create(
6090 "struct._category_t
", Int8PtrTy, ClassnfABIPtrTy, MethodListnfABIPtrTy,
6091 MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, PropertyListPtrTy,
6092 PropertyListPtrTy, IntTy);
6094 // New types for nonfragile abi messaging.
6095 CodeGen::CodeGenTypes &Types = CGM.getTypes();
6096 ASTContext &Ctx = CGM.getContext();
6098 // MessageRefTy - LLVM for:
6099 // struct _message_ref_t {
6104 // First the clang type for struct _message_ref_t
6105 RecordDecl *RD = RecordDecl::Create(
6106 Ctx, TagTypeKind::Struct, Ctx.getTranslationUnitDecl(), SourceLocation(),
6107 SourceLocation(), &Ctx.Idents.get("_message_ref_t
"));
6108 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6109 nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false,
6111 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6112 nullptr, Ctx.getObjCSelType(), nullptr, nullptr,
6113 false, ICIS_NoInit));
6114 RD->completeDefinition();
6116 MessageRefCTy = Ctx.getTagDeclType(RD);
6117 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
6118 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
6120 // MessageRefPtrTy - LLVM for struct _message_ref_t*
6121 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
6123 // SuperMessageRefTy - LLVM for:
6124 // struct _super_message_ref_t {
6125 // SUPER_IMP messenger;
6128 SuperMessageRefTy = llvm::StructType::create("struct._super_message_ref_t
",
6129 ImpnfABITy, SelectorPtrTy);
6131 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
6132 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
6135 // struct objc_typeinfo {
6136 // const void** vtable; // objc_ehtype_vtable + 2
6137 // const char* name; // c++ typeinfo string
6140 EHTypeTy = llvm::StructType::create("struct._objc_typeinfo
",
6141 llvm::PointerType::getUnqual(Int8PtrTy),
6142 Int8PtrTy, ClassnfABIPtrTy);
6143 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
6146llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
6147 FinishNonFragileABIModule();
6152void CGObjCNonFragileABIMac::AddModuleClassList(
6153 ArrayRef<llvm::GlobalValue *> Container, StringRef SymbolName,
6154 StringRef SectionName) {
6155 unsigned NumClasses = Container.size();
6160 SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
6161 for (unsigned i=0; i<NumClasses; i++)
6162 Symbols[i] = Container[i];
6164 llvm::Constant *Init =
6165 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
6169 // Section name is obtained by calling GetSectionName, which returns
6170 // sections in the __DATA segment on MachO.
6171 assert((!CGM.getTriple().isOSBinFormatMachO() ||
6172 SectionName.starts_with("__DATA
")) &&
6173 "SectionName expected to start with __DATA on MachO
");
6174 llvm::GlobalVariable *GV = new llvm::GlobalVariable(
6175 CGM.getModule(), Init->getType(), false,
6176 llvm::GlobalValue::PrivateLinkage, Init, SymbolName);
6177 GV->setAlignment(CGM.getDataLayout().getABITypeAlign(Init->getType()));
6178 GV->setSection(SectionName);
6179 CGM.addCompilerUsedGlobal(GV);
6182void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
6183 // nonfragile abi has no module definition.
6185 // Build list of all implemented class addresses in array
6186 // L_OBJC_LABEL_CLASS_$.
6188 for (unsigned i=0, NumClasses=ImplementedClasses.size(); i<NumClasses; i++) {
6189 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
6191 if (ObjCImplementationDecl *IMP = ID->getImplementation())
6192 // We are implementing a weak imported interface. Give it external linkage
6193 if (ID->isWeakImported() && !IMP->isWeakImported()) {
6194 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
6195 DefinedMetaClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
6199 AddModuleClassList(DefinedClasses, "OBJC_LABEL_CLASS_$
",
6200 GetSectionName("__objc_classlist
",
6201 "regular,no_dead_strip
"));
6203 AddModuleClassList(DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$
",
6204 GetSectionName("__objc_nlclslist
",
6205 "regular,no_dead_strip
"));
6207 // Build list of all implemented category addresses in array
6208 // L_OBJC_LABEL_CATEGORY_$.
6209 AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$
",
6210 GetSectionName("__objc_catlist
",
6211 "regular,no_dead_strip
"));
6212 AddModuleClassList(DefinedStubCategories, "OBJC_LABEL_STUB_CATEGORY_$
",
6213 GetSectionName("__objc_catlist2
",
6214 "regular,no_dead_strip
"));
6215 AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$
",
6216 GetSectionName("__objc_nlcatlist
",
6217 "regular,no_dead_strip
"));
6226bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
6227 // At various points we've experimented with using vtable-based
6228 // dispatch for all methods.
6229 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
6230 case CodeGenOptions::Legacy:
6232 case CodeGenOptions::NonLegacy:
6234 case CodeGenOptions::Mixed:
6238 // If so, see whether this selector is in the white-list of things which must
6239 // use the new dispatch convention. We lazily build a dense set for this.
6240 if (VTableDispatchMethods.empty()) {
6241 VTableDispatchMethods.insert(GetNullarySelector("alloc
"));
6242 VTableDispatchMethods.insert(GetNullarySelector("class"));
6243 VTableDispatchMethods.insert(GetNullarySelector("self
"));
6244 VTableDispatchMethods.insert(GetNullarySelector("isFlipped
"));
6245 VTableDispatchMethods.insert(GetNullarySelector("length"));
6246 VTableDispatchMethods.insert(GetNullarySelector("count
"));
6248 // These are vtable-based if GC is disabled.
6249 // Optimistically use vtable dispatch for hybrid compiles.
6250 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
6251 VTableDispatchMethods.insert(GetNullarySelector("retain
"));
6252 VTableDispatchMethods.insert(GetNullarySelector("release
"));
6253 VTableDispatchMethods.insert(GetNullarySelector("autorelease
"));
6256 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone
"));
6257 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass
"));
6258 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector
"));
6259 VTableDispatchMethods.insert(GetUnarySelector("objectForKey
"));
6260 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex
"));
6261 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString
"));
6262 VTableDispatchMethods.insert(GetUnarySelector("isEqual
"));
6264 // These are vtable-based if GC is enabled.
6265 // Optimistically use vtable dispatch for hybrid compiles.
6266 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
6267 VTableDispatchMethods.insert(GetNullarySelector("hash
"));
6268 VTableDispatchMethods.insert(GetUnarySelector("addObject
"));
6270 // "countByEnumeratingWithState:objects:count
"
6271 const IdentifierInfo *KeyIdents[] = {
6272 &CGM.getContext().Idents.get("countByEnumeratingWithState
"),
6273 &CGM.getContext().Idents.get("objects
"),
6274 &CGM.getContext().Idents.get("count
")};
6275 VTableDispatchMethods.insert(
6276 CGM.getContext().Selectors.getSelector(3, KeyIdents));
6280 return VTableDispatchMethods.count(Sel);
6298llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
6300 unsigned InstanceStart,
6301 unsigned InstanceSize,
6302 const ObjCImplementationDecl *ID) {
6303 std::string ClassName = std::string(ID->getObjCRuntimeNameAsString());
6305 CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
6306 CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
6308 bool hasMRCWeak = false;
6309 if (CGM.getLangOpts().ObjCAutoRefCount)
6310 flags |= NonFragileABI_Class_CompiledByARC;
6311 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
6312 flags |= NonFragileABI_Class_HasMRCWeakIvars;
6314 ConstantInitBuilder builder(CGM);
6315 auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy);
6317 values.addInt(ObjCTypes.IntTy, flags);
6318 values.addInt(ObjCTypes.IntTy, InstanceStart);
6319 values.addInt(ObjCTypes.IntTy, InstanceSize);
6320 values.add((flags & NonFragileABI_Class_Meta)
6321 ? GetIvarLayoutName(nullptr, ObjCTypes)
6322 : BuildStrongIvarLayout(ID, beginInstance, endInstance));
6323 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
6325 // const struct _method_list_t * const baseMethods;
6326 SmallVector<const ObjCMethodDecl*, 16> methods;
6327 if (flags & NonFragileABI_Class_Meta) {
6328 for (const auto *MD : ID->class_methods())
6329 if (!MD->isDirectMethod())
6330 methods.push_back(MD);
6332 for (const auto *MD : ID->instance_methods())
6333 if (!MD->isDirectMethod())
6334 methods.push_back(MD);
6337 values.add(emitMethodList(ID->getObjCRuntimeNameAsString(),
6338 (flags & NonFragileABI_Class_Meta)
6339 ? MethodListType::ClassMethods
6340 : MethodListType::InstanceMethods,
6343 const ObjCInterfaceDecl *OID = ID->getClassInterface();
6344 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer
");
6345 values.add(EmitProtocolList("_OBJC_CLASS_PROTOCOLS_$_
"
6346 + OID->getObjCRuntimeNameAsString(),
6347 OID->all_referenced_protocol_begin(),
6348 OID->all_referenced_protocol_end()));
6350 if (flags & NonFragileABI_Class_Meta) {
6351 values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy);
6352 values.add(GetIvarLayoutName(nullptr, ObjCTypes));
6353 values.add(EmitPropertyList(
6354 "_OBJC_$_CLASS_PROP_LIST_
" + ID->getObjCRuntimeNameAsString(),
6355 ID, ID->getClassInterface(), ObjCTypes, true));
6357 values.add(EmitIvarList(ID));
6358 values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak));
6359 values.add(EmitPropertyList(
6360 "_OBJC_$_PROP_LIST_
" + ID->getObjCRuntimeNameAsString(),
6361 ID, ID->getClassInterface(), ObjCTypes, false));
6364 llvm::SmallString<64> roLabel;
6365 llvm::raw_svector_ostream(roLabel)
6366 << ((flags & NonFragileABI_Class_Meta) ? "_OBJC_METACLASS_RO_$_
"
6367 : "_OBJC_CLASS_RO_$_
")
6370 return finishAndCreateGlobal(values, roLabel, CGM);
6383llvm::GlobalVariable *
6384CGObjCNonFragileABIMac::BuildClassObject(const ObjCInterfaceDecl *CI,
6386 llvm::Constant *IsAGV,
6387 llvm::Constant *SuperClassGV,
6388 llvm::Constant *ClassRoGV,
6389 bool HiddenVisibility) {
6390 ConstantInitBuilder builder(CGM);
6391 auto values = builder.beginStruct(ObjCTypes.ClassnfABITy);
6394 values.add(SuperClassGV);
6396 values.addNullPointer(ObjCTypes.ClassnfABIPtrTy);
6398 values.add(ObjCEmptyCacheVar);
6399 values.add(ObjCEmptyVtableVar);
6400 values.add(ClassRoGV);
6402 llvm::GlobalVariable *GV =
6403 cast<llvm::GlobalVariable>(GetClassGlobal(CI, isMetaclass, ForDefinition));
6404 values.finishAndSetAsInitializer(GV);
6406 if (CGM.getTriple().isOSBinFormatMachO())
6407 GV->setSection("__DATA, __objc_data
");
6408 GV->setAlignment(CGM.getDataLayout().getABITypeAlign(ObjCTypes.ClassnfABITy));
6409 if (!CGM.getTriple().isOSBinFormatCOFF())
6410 if (HiddenVisibility)
6411 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6415bool CGObjCNonFragileABIMac::ImplementationIsNonLazy(
6416 const ObjCImplDecl *OD) const {
6417 return OD->getClassMethod(GetNullarySelector("load
")) != nullptr ||
6418 OD->getClassInterface()->hasAttr<ObjCNonLazyClassAttr>() ||
6419 OD->hasAttr<ObjCNonLazyClassAttr>();
6422void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
6423 uint32_t &InstanceStart,
6424 uint32_t &InstanceSize) {
6425 const ASTRecordLayout &RL =
6426 CGM.getContext().getASTObjCImplementationLayout(OID);
6428 // InstanceSize is really instance end.
6429 InstanceSize = RL.getDataSize().getQuantity();
6431 // If there are no fields, the start is the same as the end.
6432 if (!RL.getFieldCount())
6433 InstanceStart = InstanceSize;
6435 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
6438static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM,
6440 IdentifierInfo &II = CGM.getContext().Idents.get(Name);
6441 TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
6442 DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
6444 const VarDecl *VD = nullptr;
6445 for (const auto *Result : DC->lookup(&II))
6446 if ((VD = dyn_cast<VarDecl>(Result)))
6450 return llvm::GlobalValue::DLLImportStorageClass;
6451 if (VD->hasAttr<DLLExportAttr>())
6452 return llvm::GlobalValue::DLLExportStorageClass;
6453 if (VD->hasAttr<DLLImportAttr>())
6454 return llvm::GlobalValue::DLLImportStorageClass;
6455 return llvm::GlobalValue::DefaultStorageClass;
6458void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
6459 if (!ObjCEmptyCacheVar) {
6461 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CacheTy, false,
6462 llvm::GlobalValue::ExternalLinkage, nullptr,
6463 "_objc_empty_cache
");
6464 if (CGM.getTriple().isOSBinFormatCOFF())
6465 ObjCEmptyCacheVar->setDLLStorageClass(getStorage(CGM, "_objc_empty_cache
"));
6467 // Only OS X with deployment version <10.9 use the empty vtable symbol
6468 const llvm::Triple &Triple = CGM.getTarget().getTriple();
6469 if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9))
6470 ObjCEmptyVtableVar =
6471 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ImpnfABITy, false,
6472 llvm::GlobalValue::ExternalLinkage, nullptr,
6473 "_objc_empty_vtable
");
6475 ObjCEmptyVtableVar =
6476 llvm::ConstantPointerNull::get(ObjCTypes.ImpnfABITy->getPointerTo());
6479 // FIXME: Is this correct (that meta class size is never computed)?
6480 uint32_t InstanceStart =
6481 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
6482 uint32_t InstanceSize = InstanceStart;
6483 uint32_t flags = NonFragileABI_Class_Meta;
6485 llvm::Constant *SuperClassGV, *IsAGV;
6487 const auto *CI = ID->getClassInterface();
6488 assert(CI && "CGObjCNonFragileABIMac::GenerateClass -
class is 0
");
6490 // Build the flags for the metaclass.
6491 bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF())
6492 ? !CI->hasAttr<DLLExportAttr>()
6493 : CI->getVisibility() == HiddenVisibility;
6495 flags |= NonFragileABI_Class_Hidden;
6497 // FIXME: why is this flag set on the metaclass?
6498 // ObjC metaclasses have no fields and don't really get constructed.
6499 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
6500 flags |= NonFragileABI_Class_HasCXXStructors;
6501 if (!ID->hasNonZeroConstructors())
6502 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
6505 if (!CI->getSuperClass()) {
6507 flags |= NonFragileABI_Class_Root;
6509 SuperClassGV = GetClassGlobal(CI, /*metaclass*/ false, NotForDefinition);
6510 IsAGV = GetClassGlobal(CI, /*metaclass*/ true, NotForDefinition);
6512 // Has a root. Current class is not a root.
6513 const ObjCInterfaceDecl *Root = ID->getClassInterface();
6514 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
6517 const auto *Super = CI->getSuperClass();
6518 IsAGV = GetClassGlobal(Root, /*metaclass*/ true, NotForDefinition);
6519 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ true, NotForDefinition);
6522 llvm::GlobalVariable *CLASS_RO_GV =
6523 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
6525 llvm::GlobalVariable *MetaTClass =
6526 BuildClassObject(CI, /*metaclass*/ true,
6527 IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden);
6528 CGM.setGVProperties(MetaTClass, CI);
6529 DefinedMetaClasses.push_back(MetaTClass);
6531 // Metadata for the class
6534 flags |= NonFragileABI_Class_Hidden;
6536 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
6537 flags |= NonFragileABI_Class_HasCXXStructors;
6539 // Set a flag to enable a runtime optimization when a class has
6540 // fields that require destruction but which don't require
6541 // anything except zero-initialization during construction. This
6542 // is most notably true of __strong and __weak types, but you can
6543 // also imagine there being C++ types with non-trivial default
6544 // constructors that merely set all fields to null.
6545 if (!ID->hasNonZeroConstructors())
6546 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
6549 if (hasObjCExceptionAttribute(CGM.getContext(), CI))
6550 flags |= NonFragileABI_Class_Exception;
6552 if (!CI->getSuperClass()) {
6553 flags |= NonFragileABI_Class_Root;
6554 SuperClassGV = nullptr;
6556 // Has a root. Current class is not a root.
6557 const auto *Super = CI->getSuperClass();
6558 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ false, NotForDefinition);
6561 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
6563 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
6565 llvm::GlobalVariable *ClassMD =
6566 BuildClassObject(CI, /*metaclass*/ false,
6567 MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden);
6568 CGM.setGVProperties(ClassMD, CI);
6569 DefinedClasses.push_back(ClassMD);
6570 ImplementedClasses.push_back(CI);
6572 // Determine if this class is also "non-lazy
".
6573 if (ImplementationIsNonLazy(ID))
6574 DefinedNonLazyClasses.push_back(ClassMD);
6576 // Force the definition of the EHType if necessary.
6577 if (flags & NonFragileABI_Class_Exception)
6578 (void) GetInterfaceEHType(CI, ForDefinition);
6579 // Make sure method definition entries are all clear for next implementation.
6580 MethodDefinitions.clear();
6591llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
6592 const ObjCProtocolDecl *PD) {
6594 // This routine is called for @protocol only. So, we must build definition
6595 // of protocol's meta-data (not a reference to it!)
6596 assert(!PD->isNonRuntimeProtocol() &&
6597 "attempting to get a protocol ref to a
static protocol.
");
6598 llvm::Constant *Init = GetOrEmitProtocol(PD);
6600 std::string ProtocolName("_OBJC_PROTOCOL_REFERENCE_$_
");
6601 ProtocolName += PD->getObjCRuntimeNameAsString();
6603 CharUnits Align = CGF.getPointerAlign();
6605 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
6607 return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
6608 PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
6609 llvm::GlobalValue::WeakAnyLinkage, Init,
6611 PTGV->setSection(GetSectionName("__objc_protorefs
",
6612 "coalesced,no_dead_strip
"));
6613 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6614 PTGV->setAlignment(Align.getAsAlign());
6615 if (!CGM.getTriple().isOSBinFormatMachO())
6616 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName));
6617 CGM.addUsedGlobal(PTGV);
6618 return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
6633void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
6634 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
6635 const char *Prefix = "_OBJC_$_CATEGORY_
";
6637 llvm::SmallString<64> ExtCatName(Prefix);
6638 ExtCatName += Interface->getObjCRuntimeNameAsString();
6639 ExtCatName += "_$_
";
6640 ExtCatName += OCD->getNameAsString();
6642 ConstantInitBuilder builder(CGM);
6643 auto values = builder.beginStruct(ObjCTypes.CategorynfABITy);
6644 values.add(GetClassName(OCD->getIdentifier()->getName()));
6645 // meta-class entry symbol
6646 values.add(GetClassGlobal(Interface, /*metaclass*/ false, NotForDefinition));
6647 std::string listName =
6648 (Interface->getObjCRuntimeNameAsString() + "_$_
" + OCD->getName()).str();
6650 SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
6651 SmallVector<const ObjCMethodDecl *, 8> classMethods;
6652 for (const auto *MD : OCD->methods()) {
6653 if (MD->isDirectMethod())
6655 if (MD->isInstanceMethod()) {
6656 instanceMethods.push_back(MD);
6658 classMethods.push_back(MD);
6662 auto instanceMethodList = emitMethodList(
6663 listName, MethodListType::CategoryInstanceMethods, instanceMethods);
6664 auto classMethodList = emitMethodList(
6665 listName, MethodListType::CategoryClassMethods, classMethods);
6666 values.add(instanceMethodList);
6667 values.add(classMethodList);
6668 // Keep track of whether we have actual metadata to emit.
6669 bool isEmptyCategory =
6670 instanceMethodList->isNullValue() && classMethodList->isNullValue();
6672 const ObjCCategoryDecl *Category =
6673 Interface->FindCategoryDeclaration(OCD->getIdentifier());
6675 SmallString<256> ExtName;
6676 llvm::raw_svector_ostream(ExtName)
6677 << Interface->getObjCRuntimeNameAsString() << "_$_
" << OCD->getName();
6679 EmitProtocolList("_OBJC_CATEGORY_PROTOCOLS_$_
" +
6680 Interface->getObjCRuntimeNameAsString() + "_$_
" +
6681 Category->getName(),
6682 Category->protocol_begin(), Category->protocol_end());
6683 auto propertyList = EmitPropertyList("_OBJC_$_PROP_LIST_
" + ExtName.str(),
6684 OCD, Category, ObjCTypes, false);
6685 auto classPropertyList =
6686 EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_
" + ExtName.str(), OCD,
6687 Category, ObjCTypes, true);
6688 values.add(protocolList);
6689 values.add(propertyList);
6690 values.add(classPropertyList);
6691 isEmptyCategory &= protocolList->isNullValue() &&
6692 propertyList->isNullValue() &&
6693 classPropertyList->isNullValue();
6695 values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy);
6696 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
6697 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
6700 if (isEmptyCategory) {
6701 // Empty category, don't emit any metadata.
6703 MethodDefinitions.clear();
6708 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
6709 values.addInt(ObjCTypes.IntTy, Size);
6711 llvm::GlobalVariable *GCATV =
6712 finishAndCreateGlobal(values, ExtCatName.str(), CGM);
6713 CGM.addCompilerUsedGlobal(GCATV);
6714 if (Interface->hasAttr<ObjCClassStubAttr>())
6715 DefinedStubCategories.push_back(GCATV);
6717 DefinedCategories.push_back(GCATV);
6719 // Determine if this category is also "non-lazy
".
6720 if (ImplementationIsNonLazy(OCD))
6721 DefinedNonLazyCategories.push_back(GCATV);
6722 // method definition entries must be clear for next implementation.
6723 MethodDefinitions.clear();
6735void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
6736 const ObjCMethodDecl *MD,
6738 auto method = builder.beginStruct(ObjCTypes.MethodTy);
6739 method.add(GetMethodVarName(MD->getSelector()));
6740 method.add(GetMethodVarType(MD));
6743 // Protocol methods have no implementation. So, this entry is always NULL.
6744 method.addNullPointer(ObjCTypes.Int8PtrProgramASTy);
6746 llvm::Function *fn = GetMethodDefinition(MD);
6747 assert(fn && "no definition
for method?
");
6751 method.finishAndAddTo(builder);
6763CGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind,
6764 ArrayRef<const ObjCMethodDecl *> methods) {
6765 // Return null for empty list.
6766 if (methods.empty())
6767 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
6772 case MethodListType::CategoryInstanceMethods:
6773 prefix = "_OBJC_$_CATEGORY_INSTANCE_METHODS_
";
6774 forProtocol = false;
6776 case MethodListType::CategoryClassMethods:
6777 prefix = "_OBJC_$_CATEGORY_CLASS_METHODS_
";
6778 forProtocol = false;
6780 case MethodListType::InstanceMethods:
6781 prefix = "_OBJC_$_INSTANCE_METHODS_
";
6782 forProtocol = false;
6784 case MethodListType::ClassMethods:
6785 prefix = "_OBJC_$_CLASS_METHODS_
";
6786 forProtocol = false;
6789 case MethodListType::ProtocolInstanceMethods:
6790 prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_
";
6793 case MethodListType::ProtocolClassMethods:
6794 prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_
";
6797 case MethodListType::OptionalProtocolInstanceMethods:
6798 prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_
";
6801 case MethodListType::OptionalProtocolClassMethods:
6802 prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_
";
6807 ConstantInitBuilder builder(CGM);
6808 auto values = builder.beginStruct();
6810 // sizeof(struct _objc_method)
6811 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
6812 values.addInt(ObjCTypes.IntTy, Size);
6814 values.addInt(ObjCTypes.IntTy, methods.size());
6815 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
6816 for (auto MD : methods)
6817 emitMethodConstant(methodArray, MD, forProtocol);
6818 methodArray.finishAndAddTo(values);
6820 llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM);
6821 CGM.addCompilerUsedGlobal(GV);
6827llvm::GlobalVariable *
6828CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6829 const ObjCIvarDecl *Ivar) {
6830 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
6831 llvm::SmallString<64> Name("OBJC_IVAR_$_
");
6832 Name += Container->getObjCRuntimeNameAsString();
6834 Name += Ivar->getName();
6835 llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name);
6836 if (!IvarOffsetGV) {
6838 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.IvarOffsetVarTy,
6839 false, llvm::GlobalValue::ExternalLinkage,
6840 nullptr, Name.str());
6841 if (CGM.getTriple().isOSBinFormatCOFF()) {
6842 bool IsPrivateOrPackage =
6843 Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6844 Ivar->getAccessControl() == ObjCIvarDecl::Package;
6846 const ObjCInterfaceDecl *ContainingID = Ivar->getContainingInterface();
6848 if (ContainingID->hasAttr<DLLImportAttr>())
6850 ->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
6851 else if (ContainingID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage)
6853 ->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
6856 return IvarOffsetGV;
6860CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6861 const ObjCIvarDecl *Ivar,
6862 unsigned long int Offset) {
6863 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
6864 IvarOffsetGV->setInitializer(
6865 llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset));
6866 IvarOffsetGV->setAlignment(
6867 CGM.getDataLayout().getABITypeAlign(ObjCTypes.IvarOffsetVarTy));
6869 if (!CGM.getTriple().isOSBinFormatCOFF()) {
6870 // FIXME: This matches gcc, but shouldn't the visibility be set on the use
6871 // as well (i.e., in ObjCIvarOffsetVariable).
6872 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6873 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
6874 ID->getVisibility() == HiddenVisibility)
6875 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6877 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
6880 // If ID's layout is known, then make the global constant. This serves as a
6881 // useful assertion: we'll never use this variable to calculate ivar offsets,
6882 // so if the runtime tries to patch it then we should crash.
6883 if (isClassLayoutKnownStatically(ID))
6884 IvarOffsetGV->setConstant(true);
6886 if (CGM.getTriple().isOSBinFormatMachO())
6887 IvarOffsetGV->setSection("__DATA, __objc_ivar
");
6888 return IvarOffsetGV;
6908llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
6909 const ObjCImplementationDecl *ID) {
6911 ConstantInitBuilder builder(CGM);
6912 auto ivarList = builder.beginStruct();
6913 ivarList.addInt(ObjCTypes.IntTy,
6914 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy));
6915 auto ivarCountSlot = ivarList.addPlaceholder();
6916 auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy);
6918 const ObjCInterfaceDecl *OID = ID->getClassInterface();
6919 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface
");
6921 // FIXME. Consolidate this with similar code in GenerateClass.
6923 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
6924 IVD; IVD = IVD->getNextIvar()) {
6925 // Ignore unnamed bit-fields.
6926 if (!IVD->getDeclName())
6929 auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy);
6930 ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD,
6931 ComputeIvarBaseOffset(CGM, ID, IVD)));
6932 ivar.add(GetMethodVarName(IVD->getIdentifier()));
6933 ivar.add(GetMethodVarType(IVD));
6934 llvm::Type *FieldTy =
6935 CGM.getTypes().ConvertTypeForMem(IVD->getType());
6936 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
6937 unsigned Align = CGM.getContext().getPreferredTypeAlign(
6938 IVD->getType().getTypePtr()) >> 3;
6939 Align = llvm::Log2_32(Align);
6940 ivar.addInt(ObjCTypes.IntTy, Align);
6941 // NOTE. Size of a bitfield does not match gcc's, because of the
6942 // way bitfields are treated special in each. But I am told that
6943 // 'size' for bitfield ivars is ignored by the runtime so it does
6944 // not matter. If it matters, there is enough info to get the
6946 ivar.addInt(ObjCTypes.IntTy, Size);
6947 ivar.finishAndAddTo(ivars);
6949 // Return null for empty list.
6950 if (ivars.empty()) {
6953 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
6956 auto ivarCount = ivars.size();
6957 ivars.finishAndAddTo(ivarList);
6958 ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount);
6960 const char *Prefix = "_OBJC_$_INSTANCE_VARIABLES_
";
6961 llvm::GlobalVariable *GV = finishAndCreateGlobal(
6962 ivarList, Prefix + OID->getObjCRuntimeNameAsString(), CGM);
6963 CGM.addCompilerUsedGlobal(GV);
6967llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
6968 const ObjCProtocolDecl *PD) {
6969 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
6971 assert(!PD->isNonRuntimeProtocol() &&
6972 "attempting to GetOrEmit a non-runtime protocol
");
6974 // We use the initializer as a marker of whether this is a forward
6975 // reference or not. At module finalization we add the empty
6976 // contents for protocols which were referenced but never defined.
6977 llvm::SmallString<64> Protocol;
6978 llvm::raw_svector_ostream(Protocol) << "_OBJC_PROTOCOL_$_
"
6979 << PD->getObjCRuntimeNameAsString();
6981 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
6982 false, llvm::GlobalValue::ExternalLinkage,
6984 if (!CGM.getTriple().isOSBinFormatMachO())
6985 Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol));
7011llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
7012 const ObjCProtocolDecl *PD) {
7013 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
7015 // Early exit if a defining object has already been generated.
7016 if (Entry && Entry->hasInitializer())
7019 // Use the protocol definition, if there is one.
7020 assert(PD->hasDefinition() &&
7021 "emitting protocol metadata without definition
");
7022 PD = PD->getDefinition();
7024 auto methodLists = ProtocolMethodLists::get(PD);
7026 ConstantInitBuilder builder(CGM);
7027 auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy);
7030 values.addNullPointer(ObjCTypes.ObjectPtrTy);
7031 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
7032 values.add(EmitProtocolList("_OBJC_$_PROTOCOL_REFS_
"
7033 + PD->getObjCRuntimeNameAsString(),
7034 PD->protocol_begin(),
7035 PD->protocol_end()));
7036 values.add(methodLists.emitMethodList(this, PD,
7037 ProtocolMethodLists::RequiredInstanceMethods));
7038 values.add(methodLists.emitMethodList(this, PD,
7039 ProtocolMethodLists::RequiredClassMethods));
7040 values.add(methodLists.emitMethodList(this, PD,
7041 ProtocolMethodLists::OptionalInstanceMethods));
7042 values.add(methodLists.emitMethodList(this, PD,
7043 ProtocolMethodLists::OptionalClassMethods));
7044 values.add(EmitPropertyList(
7045 "_OBJC_$_PROP_LIST_
" + PD->getObjCRuntimeNameAsString(),
7046 nullptr, PD, ObjCTypes, false));
7048 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
7049 values.addInt(ObjCTypes.IntTy, Size);
7050 values.addInt(ObjCTypes.IntTy, 0);
7051 values.add(EmitProtocolMethodTypes("_OBJC_$_PROTOCOL_METHOD_TYPES_
"
7052 + PD->getObjCRuntimeNameAsString(),
7053 methodLists.emitExtendedTypesArray(this),
7056 // const char *demangledName;
7057 values.addNullPointer(ObjCTypes.Int8PtrTy);
7059 values.add(EmitPropertyList(
7060 "_OBJC_$_CLASS_PROP_LIST_
" + PD->getObjCRuntimeNameAsString(),
7061 nullptr, PD, ObjCTypes, true));
7064 // Already created, fix the linkage and update the initializer.
7065 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
7066 values.finishAndSetAsInitializer(Entry);
7068 llvm::SmallString<64> symbolName;
7069 llvm::raw_svector_ostream(symbolName)
7070 << "_OBJC_PROTOCOL_$_
" << PD->getObjCRuntimeNameAsString();
7072 Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(),
7074 llvm::GlobalValue::WeakAnyLinkage);
7075 if (!CGM.getTriple().isOSBinFormatMachO())
7076 Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName));
7078 Protocols[PD->getIdentifier()] = Entry;
7080 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
7081 CGM.addUsedGlobal(Entry);
7083 // Use this protocol meta-data to build protocol list table in section
7084 // __DATA, __objc_protolist
7085 llvm::SmallString<64> ProtocolRef;
7086 llvm::raw_svector_ostream(ProtocolRef) << "_OBJC_LABEL_PROTOCOL_$_
"
7087 << PD->getObjCRuntimeNameAsString();
7089 llvm::GlobalVariable *PTGV =
7090 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
7091 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
7093 if (!CGM.getTriple().isOSBinFormatMachO())
7094 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef));
7096 CGM.getDataLayout().getABITypeAlign(ObjCTypes.ProtocolnfABIPtrTy));
7097 PTGV->setSection(GetSectionName("__objc_protolist
",
7098 "coalesced,no_dead_strip
"));
7099 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
7100 CGM.addUsedGlobal(PTGV);
7113CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
7114 ObjCProtocolDecl::protocol_iterator begin,
7115 ObjCProtocolDecl::protocol_iterator end) {
7116 // Just return null for empty protocol lists
7117 auto Protocols = GetRuntimeProtocolList(begin, end);
7118 if (Protocols.empty())
7119 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
7121 SmallVector<llvm::Constant *, 16> ProtocolRefs;
7122 ProtocolRefs.reserve(Protocols.size());
7124 for (const auto *PD : Protocols)
7125 ProtocolRefs.push_back(GetProtocolRef(PD));
7127 // If all of the protocols in the protocol list are objc_non_runtime_protocol
7129 if (ProtocolRefs.size() == 0)
7130 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
7132 // FIXME: We shouldn't need to do this lookup here, should we?
7133 SmallString<256> TmpName;
7134 Name.toVector(TmpName);
7135 llvm::GlobalVariable *GV =
7136 CGM.getModule().getGlobalVariable(TmpName.str(), true);
7140 ConstantInitBuilder builder(CGM);
7141 auto values = builder.beginStruct();
7142 auto countSlot = values.addPlaceholder();
7144 // A null-terminated array of protocols.
7145 auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy);
7146 for (auto const &proto : ProtocolRefs)
7148 auto count = array.size();
7149 array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy);
7151 array.finishAndAddTo(values);
7152 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
7154 GV = finishAndCreateGlobal(values, Name, CGM);
7155 CGM.addCompilerUsedGlobal(GV);
7165LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
7166 CodeGen::CodeGenFunction &CGF,
7168 llvm::Value *BaseValue,
7169 const ObjCIvarDecl *Ivar,
7170 unsigned CVRQualifiers) {
7171 ObjCInterfaceDecl *ID = ObjectTy->castAs<ObjCObjectType>()->getInterface();
7172 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
7173 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
7178CGObjCNonFragileABIMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
7179 const ObjCInterfaceDecl *Interface,
7180 const ObjCIvarDecl *Ivar) {
7181 llvm::Value *IvarOffsetValue;
7182 if (isClassLayoutKnownStatically(Interface)) {
7183 IvarOffsetValue = llvm::ConstantInt::get(
7184 ObjCTypes.IvarOffsetVarTy,
7185 ComputeIvarBaseOffset(CGM, Interface->getImplementation(), Ivar));
7187 llvm::GlobalVariable *GV = ObjCIvarOffsetVariable(Interface, Ivar);
7189 CGF.Builder.CreateAlignedLoad(GV->getValueType(), GV,
7190 CGF.getSizeAlign(), "ivar
");
7191 if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
7192 cast<llvm::LoadInst>(IvarOffsetValue)
7193 ->setMetadata(llvm::LLVMContext::MD_invariant_load,
7194 llvm::MDNode::get(VMContext, std::nullopt));
7197 // This could be 32bit int or 64bit integer depending on the architecture.
7198 // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
7199 // as this is what caller always expects.
7200 if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
7201 IvarOffsetValue = CGF.Builder.CreateIntCast(
7202 IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv
");
7203 return IvarOffsetValue;
7206static void appendSelectorForMessageRefTable(std::string &buffer,
7207 Selector selector) {
7208 if (selector.isUnarySelector()) {
7209 buffer += selector.getNameForSlot(0);
7213 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
7214 buffer += selector.getNameForSlot(i);
7230CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
7231 ReturnValueSlot returnSlot,
7232 QualType resultType,
7237 const CallArgList &formalArgs,
7238 const ObjCMethodDecl *method) {
7239 // Compute the actual arguments.
7242 // First argument: the receiver / super-call structure.
7244 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
7245 args.add(RValue::get(arg0), arg0Type);
7247 // Second argument: a pointer to the message ref structure. Leave
7248 // the actual argument value blank for now.
7249 args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy);
7251 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
7253 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
7255 NullReturnState nullReturn;
7257 // Find the function to call and the mangled name for the message
7258 // ref structure. Using a different mangled name wouldn't actually
7259 // be a problem; it would just be a waste.
7261 // The runtime currently never uses vtable dispatch for anything
7262 // except normal, non-super message-sends.
7263 // FIXME: don't use this for that.
7264 llvm::FunctionCallee fn = nullptr;
7265 std::string messageRefName("_
");
7266 if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
7268 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
7269 messageRefName += "objc_msgSendSuper2_stret_fixup
";
7271 nullReturn.init(CGF, arg0);
7272 fn = ObjCTypes.getMessageSendStretFixupFn();
7273 messageRefName += "objc_msgSend_stret_fixup
";
7275 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
7276 fn = ObjCTypes.getMessageSendFpretFixupFn();
7277 messageRefName += "objc_msgSend_fpret_fixup
";
7280 fn = ObjCTypes.getMessageSendSuper2FixupFn();
7281 messageRefName += "objc_msgSendSuper2_fixup
";
7283 fn = ObjCTypes.getMessageSendFixupFn();
7284 messageRefName += "objc_msgSend_fixup
";
7287 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend
");
7288 messageRefName += '_';
7290 // Append the selector name, except use underscores anywhere we
7291 // would have used colons.
7292 appendSelectorForMessageRefTable(messageRefName, selector);
7294 llvm::GlobalVariable *messageRef
7295 = CGM.getModule().getGlobalVariable(messageRefName);
7297 // Build the message ref structure.
7298 ConstantInitBuilder builder(CGM);
7299 auto values = builder.beginStruct();
7300 values.add(cast<llvm::Constant>(fn.getCallee()));
7301 values.add(GetMethodVarName(selector));
7302 messageRef = values.finishAndCreateGlobal(messageRefName,
7303 CharUnits::fromQuantity(16),
7305 llvm::GlobalValue::WeakAnyLinkage);
7306 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
7307 messageRef->setSection(GetSectionName("__objc_msgrefs
", "coalesced
"));
7310 bool requiresnullCheck = false;
7311 if (CGM.getLangOpts().ObjCAutoRefCount && method)
7312 for (const auto *ParamDecl : method->parameters()) {
7313 if (ParamDecl->isDestroyedInCallee()) {
7314 if (!nullReturn.NullBB)
7315 nullReturn.init(CGF, arg0);
7316 requiresnullCheck = true;
7322 Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy),
7323 ObjCTypes.MessageRefTy, CGF.getPointerAlign());
7325 // Update the message ref argument.
7326 args[1].setRValue(RValue::get(mref, CGF));
7328 // Load the function to call from the message ref table.
7329 Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0);
7330 llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn
");
7332 calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType);
7333 CGCallee callee(CGCalleeInfo(), calleePtr);
7335 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
7336 return nullReturn.complete(CGF, returnSlot, result, resultType, formalArgs,
7337 requiresnullCheck ? method : nullptr);
7342CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
7343 ReturnValueSlot Return,
7344 QualType ResultType,
7346 llvm::Value *Receiver,
7347 const CallArgList &CallArgs,
7348 const ObjCInterfaceDecl *Class,
7349 const ObjCMethodDecl *Method) {
7350 return isVTableDispatchedSelector(Sel)
7351 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
7352 Receiver, CGF.getContext().getObjCIdType(),
7353 false, CallArgs, Method)
7354 : EmitMessageSend(CGF, Return, ResultType, Sel,
7355 Receiver, CGF.getContext().getObjCIdType(),
7356 false, CallArgs, Method, Class, ObjCTypes);
7360CGObjCNonFragileABIMac::GetClassGlobal(const ObjCInterfaceDecl *ID,
7362 ForDefinition_t isForDefinition) {
7364 (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix());
7365 return GetClassGlobal((prefix + ID->getObjCRuntimeNameAsString()).str(),
7367 ID->isWeakImported(),
7369 && CGM.getTriple().isOSBinFormatCOFF()
7370 && ID->hasAttr<DLLImportAttr>());
7374CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name,
7375 ForDefinition_t IsForDefinition,
7376 bool Weak, bool DLLImport) {
7377 llvm::GlobalValue::LinkageTypes L =
7378 Weak ? llvm::GlobalValue::ExternalWeakLinkage
7379 : llvm::GlobalValue::ExternalLinkage;
7381 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
7382 if (!GV || GV->getValueType() != ObjCTypes.ClassnfABITy) {
7383 auto *NewGV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false, L,
7387 NewGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
7390 GV->replaceAllUsesWith(NewGV);
7391 GV->eraseFromParent();
7394 CGM.getModule().insertGlobalVariable(GV);
7397 assert(GV->getLinkage() == L);
7402CGObjCNonFragileABIMac::GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID) {
7403 llvm::Constant *ClassGV = GetClassGlobal(ID, /*metaclass*/ false,
7406 if (!ID->hasAttr<ObjCClassStubAttr>())
7409 ClassGV = llvm::ConstantExpr::getPointerCast(ClassGV, ObjCTypes.Int8PtrTy);
7411 // Stub classes are pointer-aligned. Classrefs pointing at stub classes
7412 // must set the least significant bit set to 1.
7413 auto *Idx = llvm::ConstantInt::get(CGM.Int32Ty, 1);
7414 return llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, ClassGV, Idx);
7418CGObjCNonFragileABIMac::EmitLoadOfClassRef(CodeGenFunction &CGF,
7419 const ObjCInterfaceDecl *ID,
7420 llvm::GlobalVariable *Entry) {
7421 if (ID && ID->hasAttr<ObjCClassStubAttr>()) {
7422 // Classrefs pointing at Objective-C stub classes must be loaded by calling
7423 // a special runtime function.
7424 return CGF.EmitRuntimeCall(
7425 ObjCTypes.getLoadClassrefFn(), Entry, "load_classref_result
");
7428 CharUnits Align = CGF.getPointerAlign();
7429 return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry, Align);
7433CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF,
7435 const ObjCInterfaceDecl *ID) {
7436 llvm::GlobalVariable *&Entry = ClassReferences[II];
7439 llvm::Constant *ClassGV;
7441 ClassGV = GetClassGlobalForClassRef(ID);
7443 ClassGV = GetClassGlobal((getClassSymbolPrefix() + II->getName()).str(),
7445 assert(ClassGV->getType() == ObjCTypes.ClassnfABIPtrTy &&
7446 "classref was emitted with the wrong
type?
");
7449 std::string SectionName =
7450 GetSectionName("__objc_classrefs
", "regular,no_dead_strip
");
7451 Entry = new llvm::GlobalVariable(
7452 CGM.getModule(), ClassGV->getType(), false,
7453 getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV,
7454 "OBJC_CLASSLIST_REFERENCES_$_
");
7455 Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
7456 if (!ID || !ID->hasAttr<ObjCClassStubAttr>())
7457 Entry->setSection(SectionName);
7459 CGM.addCompilerUsedGlobal(Entry);
7462 return EmitLoadOfClassRef(CGF, ID, Entry);
7465llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
7466 const ObjCInterfaceDecl *ID) {
7467 // If the class has the objc_runtime_visible attribute, we need to
7468 // use the Objective-C runtime to get the class.
7469 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
7470 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
7472 return EmitClassRefFromId(CGF, ID->getIdentifier(), ID);
7475llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
7476 CodeGenFunction &CGF) {
7477 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool
");
7478 return EmitClassRefFromId(CGF, II, nullptr);
7482CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
7483 const ObjCInterfaceDecl *ID) {
7484 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
7487 llvm::Constant *ClassGV = GetClassGlobalForClassRef(ID);
7488 std::string SectionName =
7489 GetSectionName("__objc_superrefs
", "regular,no_dead_strip
");
7490 Entry = new llvm::GlobalVariable(CGM.getModule(), ClassGV->getType(), false,
7491 llvm::GlobalValue::PrivateLinkage, ClassGV,
7492 "OBJC_CLASSLIST_SUP_REFS_$_
");
7493 Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
7494 Entry->setSection(SectionName);
7495 CGM.addCompilerUsedGlobal(Entry);
7498 return EmitLoadOfClassRef(CGF, ID, Entry);
7504llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF,
7505 const ObjCInterfaceDecl *ID,
7507 CharUnits Align = CGF.getPointerAlign();
7508 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
7510 auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition);
7511 std::string SectionName =
7512 GetSectionName("__objc_superrefs
", "regular,no_dead_strip
");
7513 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
7514 false, llvm::GlobalValue::PrivateLinkage,
7515 MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_
");
7516 Entry->setAlignment(Align.getAsAlign());
7517 Entry->setSection(SectionName);
7518 CGM.addCompilerUsedGlobal(Entry);
7521 return CGF.Builder.CreateAlignedLoad(ObjCTypes.ClassnfABIPtrTy, Entry, Align);
7526llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
7527 const ObjCInterfaceDecl *ID) {
7528 if (ID->isWeakImported()) {
7529 auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
7531 assert(!isa<llvm::GlobalVariable>(ClassGV) ||
7532 cast<llvm::GlobalVariable>(ClassGV)->hasExternalWeakLinkage());
7535 return EmitClassRef(CGF, ID);
7542CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
7543 ReturnValueSlot Return,
7544 QualType ResultType,
7546 const ObjCInterfaceDecl *Class,
7547 bool isCategoryImpl,
7548 llvm::Value *Receiver,
7549 bool IsClassMessage,
7550 const CodeGen::CallArgList &CallArgs,
7551 const ObjCMethodDecl *Method) {
7553 // Create and init a super structure; this is a (receiver, class)
7554 // pair we will pass to objc_msgSendSuper.
7555 RawAddress ObjCSuper = CGF.CreateTempAlloca(
7556 ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super
");
7558 llvm::Value *ReceiverAsObject =
7559 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
7560 CGF.Builder.CreateStore(ReceiverAsObject,
7561 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
7563 // If this is a class message the metaclass is passed as the target.
7564 llvm::Value *Target;
7566 Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported());
7568 Target = EmitSuperClassRef(CGF, Class);
7570 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
7572 llvm::Type *ClassTy =
7573 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
7574 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
7575 CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
7577 return (isVTableDispatchedSelector(Sel))
7578 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
7579 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
7580 true, CallArgs, Method)
7581 : EmitMessageSend(CGF, Return, ResultType, Sel,
7582 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
7583 true, CallArgs, Method, Class, ObjCTypes);
7586llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
7588 Address Addr = EmitSelectorAddr(Sel);
7590 llvm::LoadInst* LI = CGF.Builder.CreateLoad(Addr);
7591 LI->setMetadata(llvm::LLVMContext::MD_invariant_load,
7592 llvm::MDNode::get(VMContext, std::nullopt));
7596ConstantAddress CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) {
7597 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
7598 CharUnits Align = CGM.getPointerAlign();
7600 std::string SectionName =
7601 GetSectionName("__objc_selrefs
", "literal_pointers,no_dead_strip
");
7602 Entry = new llvm::GlobalVariable(
7603 CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
7604 getLinkageTypeForObjCMetadata(CGM, SectionName), GetMethodVarName(Sel),
7605 "OBJC_SELECTOR_REFERENCES_
");
7606 Entry->setExternallyInitialized(true);
7607 Entry->setSection(SectionName);
7608 Entry->setAlignment(Align.getAsAlign());
7609 CGM.addCompilerUsedGlobal(Entry);
7612 return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align);
7618void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
7621 llvm::Value *ivarOffset) {
7622 llvm::Type * SrcTy = src->getType();
7623 if (!isa<llvm::PointerType>(SrcTy)) {
7624 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
7625 assert(Size <= 8 && "does
not support size > 8
");
7626 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7627 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
7628 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7630 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7631 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
7632 ObjCTypes.PtrObjectPtrTy);
7633 llvm::Value *args[] = {src, dstVal, ivarOffset};
7634 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
7640void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
7641 CodeGen::CodeGenFunction &CGF,
7642 llvm::Value *src, Address dst) {
7643 llvm::Type * SrcTy = src->getType();
7644 if (!isa<llvm::PointerType>(SrcTy)) {
7645 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
7646 assert(Size <= 8 && "does
not support size > 8
");
7647 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7648 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
7649 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7651 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7652 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
7653 ObjCTypes.PtrObjectPtrTy);
7654 llvm::Value *args[] = {src, dstVal};
7655 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
7656 args, "weakassign
");
7659void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
7660 CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr,
7661 llvm::Value *Size) {
7662 llvm::Value *args[] = {DestPtr.emitRawPointer(CGF),
7663 SrcPtr.emitRawPointer(CGF), Size};
7664 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
7670llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
7671 CodeGen::CodeGenFunction &CGF,
7672 Address AddrWeakObj) {
7673 llvm::Type *DestTy = AddrWeakObj.getElementType();
7674 llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast(
7675 AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy);
7676 llvm::Value *read_weak =
7677 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(),
7678 AddrWeakObjVal, "weakread
");
7679 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
7686void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
7687 llvm::Value *src, Address dst) {
7688 llvm::Type * SrcTy = src->getType();
7689 if (!isa<llvm::PointerType>(SrcTy)) {
7690 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
7691 assert(Size <= 8 && "does
not support size > 8
");
7692 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7693 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
7694 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7696 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7697 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
7698 ObjCTypes.PtrObjectPtrTy);
7699 llvm::Value *args[] = {src, dstVal};
7700 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
7701 args, "weakassign
");
7707void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
7708 llvm::Value *src, Address dst,
7710 llvm::Type * SrcTy = src->getType();
7711 if (!isa<llvm::PointerType>(SrcTy)) {
7712 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
7713 assert(Size <= 8 && "does
not support size > 8
");
7714 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7715 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
7716 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7718 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7719 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
7720 ObjCTypes.PtrObjectPtrTy);
7721 llvm::Value *args[] = {src, dstVal};
7723 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
7724 args, "globalassign
");
7726 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
7727 args, "threadlocalassign
");
7731CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
7732 const ObjCAtSynchronizedStmt &S) {
7733 EmitAtSynchronizedStmt(CGF, S, ObjCTypes.getSyncEnterFn(),
7734 ObjCTypes.getSyncExitFn());
7738CGObjCNonFragileABIMac::GetEHType(QualType T) {
7739 // There's a particular fixed type info for 'id'.
7740 if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
7741 auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id
");
7744 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
7745 llvm::GlobalValue::ExternalLinkage, nullptr,
7747 if (CGM.getTriple().isOSBinFormatCOFF())
7748 IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id
"));
7753 // All other types should be Objective-C interface pointer types.
7754 const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
7757 const ObjCInterfaceType *IT = PT->getInterfaceType();
7758 assert(IT && "Invalid
@catch type.
");
7760 return GetInterfaceEHType(IT->getDecl(), NotForDefinition);
7763void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
7764 const ObjCAtTryStmt &S) {
7765 EmitTryCatchStmt(CGF, S, ObjCTypes.getObjCBeginCatchFn(),
7766 ObjCTypes.getObjCEndCatchFn(),
7767 ObjCTypes.getExceptionRethrowFn());
7771void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
7772 const ObjCAtThrowStmt &S,
7773 bool ClearInsertionPoint) {
7774 if (const Expr *ThrowExpr = S.getThrowExpr()) {
7775 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
7776 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
7777 llvm::CallBase *Call =
7778 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception);
7779 Call->setDoesNotReturn();
7781 llvm::CallBase *Call =
7782 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn());
7783 Call->setDoesNotReturn();
7786 CGF.Builder.CreateUnreachable();
7787 if (ClearInsertionPoint)
7788 CGF.Builder.ClearInsertionPoint();
7792CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
7793 ForDefinition_t IsForDefinition) {
7794 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
7795 StringRef ClassName = ID->getObjCRuntimeNameAsString();
7797 // If we don't need a definition, return the entry if found or check
7798 // if we use an external reference.
7799 if (!IsForDefinition) {
7803 // If this type (or a super class) has the __objc_exception__
7804 // attribute, emit an external reference.
7805 if (hasObjCExceptionAttribute(CGM.getContext(), ID)) {
7806 std::string EHTypeName = ("OBJC_EHTYPE_$_
" + ClassName).str();
7807 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
7808 false, llvm::GlobalValue::ExternalLinkage,
7809 nullptr, EHTypeName);
7810 CGM.setGVProperties(Entry, ID);
7815 // Otherwise we need to either make a new entry or fill in the initializer.
7816 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition
");
7818 std::string VTableName = "objc_ehtype_vtable
";
7819 auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName);
7822 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, false,
7823 llvm::GlobalValue::ExternalLinkage, nullptr,
7825 if (CGM.getTriple().isOSBinFormatCOFF())
7826 VTableGV->setDLLStorageClass(getStorage(CGM, VTableName));
7829 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
7830 ConstantInitBuilder builder(CGM);
7831 auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
7833 llvm::ConstantExpr::getInBoundsGetElementPtr(VTableGV->getValueType(),
7834 VTableGV, VTableIdx));
7835 values.add(GetClassName(ClassName));
7836 values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition));
7838 llvm::GlobalValue::LinkageTypes L = IsForDefinition
7839 ? llvm::GlobalValue::ExternalLinkage
7840 : llvm::GlobalValue::WeakAnyLinkage;
7842 values.finishAndSetAsInitializer(Entry);
7843 Entry->setAlignment(CGM.getPointerAlign().getAsAlign());
7845 Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_
" + ClassName,
7846 CGM.getPointerAlign(),
7849 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
7850 CGM.setGVProperties(Entry, ID);
7852 assert(Entry->getLinkage() == L);
7854 if (!CGM.getTriple().isOSBinFormatCOFF())
7855 if (ID->getVisibility() == HiddenVisibility)
7856 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
7858 if (IsForDefinition)
7859 if (CGM.getTriple().isOSBinFormatMachO())
7860 Entry->setSection("__DATA,__objc_const
");
7867CodeGen::CGObjCRuntime *
7868CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
7869 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7870 case ObjCRuntime::FragileMacOSX:
7871 return new CGObjCMac(CGM);
7873 case ObjCRuntime::MacOSX:
7874 case ObjCRuntime::iOS:
7875 case ObjCRuntime::WatchOS:
7876 return new CGObjCNonFragileABIMac(CGM);
7878 case ObjCRuntime::GNUstep:
7879 case ObjCRuntime::GCC:
7880 case ObjCRuntime::ObjFW:
7881 llvm_unreachable("these runtimes are
not Mac runtimes
");
7883 llvm_unreachable("bad runtime
");
Defines the clang::ASTContext interface.
ASTImporterLookupTable & LT
@ FragileABI_Class_Meta
Is a meta-class.
@ FragileABI_Class_Hidden
Has hidden visibility.
@ FragileABI_Class_Factory
Apparently: is not a meta-class.
@ FragileABI_Class_HasCXXStructors
Has a non-trivial constructor or destructor.
@ FragileABI_Class_HasMRCWeakIvars
Class implementation was compiled under MRC and has MRC weak ivars.
@ FragileABI_Class_CompiledByARC
Class implementation was compiled under ARC.
static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT, bool pointee=false)
static bool hasWeakMember(QualType type)
static std::string getBlockLayoutInfoString(const SmallVectorImpl< CGObjCCommonMac::RUN_SKIP > &RunSkipBlockVars, bool HasCopyDisposeHelpers)
static llvm::StringMapEntry< llvm::GlobalVariable * > & GetConstantStringEntry(llvm::StringMap< llvm::GlobalVariable * > &Map, const StringLiteral *Literal, unsigned &StringLength)
static llvm::GlobalValue::LinkageTypes getLinkageTypeForObjCMetadata(CodeGenModule &CGM, StringRef Section)
static void addIfPresent(llvm::DenseSet< llvm::Value * > &S, Address V)
static void PushProtocolProperties(llvm::SmallPtrSet< const IdentifierInfo *, 16 > &PropertySet, SmallVectorImpl< const ObjCPropertyDecl * > &Properties, const ObjCProtocolDecl *Proto, bool IsClassProperty)
static llvm::GlobalVariable * finishAndCreateGlobal(ConstantInitBuilder::StructBuilder &Builder, const llvm::Twine &Name, CodeGenModule &CGM)
A helper function to create an internal or private global variable.
static bool hasMRCWeakIvars(CodeGenModule &CGM, const ObjCImplementationDecl *ID)
For compatibility, we only want to set the "HasMRCWeakIvars" flag (and actually fill in a layout stri...
@ kCFTaggedObjectID_Integer
@ NonFragileABI_Class_HasCXXDestructorOnly
Class has non-trivial destructors, but zero-initialization is okay.
@ NonFragileABI_Class_Hidden
Has hidden visibility.
@ NonFragileABI_Class_HasCXXStructors
Has a non-trivial constructor or destructor.
@ NonFragileABI_Class_Exception
Has the exception attribute.
@ NonFragileABI_Class_HasIvarReleaser
(Obsolete) ARC-specific: this class has a .release_ivars method
@ NonFragileABI_Class_Root
Is a root class.
@ NonFragileABI_Class_Meta
Is a meta-class.
@ NonFragileABI_Class_HasMRCWeakIvars
Class implementation was compiled under MRC and has MRC weak ivars.
@ NonFragileABI_Class_CompiledByARC
Class implementation was compiled under ARC.
static llvm::Constant * getConstantGEP(llvm::LLVMContext &VMContext, llvm::GlobalVariable *C, unsigned idx0, unsigned idx1)
getConstantGEP() - Help routine to construct simple GEPs.
static bool hasObjCExceptionAttribute(ASTContext &Context, const ObjCInterfaceDecl *OID)
hasObjCExceptionAttribute - Return true if this class or any super class has the objc_exception attri...
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
Defines the clang::LangOptions interface.
llvm::MachO::Target Target
Defines the Objective-C statement AST node classes.
__device__ __2f16 float __ockl_bool s
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CanQualType getCanonicalParamType(QualType T) const
Return the canonical parameter type corresponding to the specific potentially non-canonical one.
QualType getObjCClassType() const
Represents the Objective-C Class type.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const ASTRecordLayout & getASTObjCImplementationLayout(const ObjCImplementationDecl *D) const
Get or compute information about the layout of the specified Objective-C implementation.
const LangOptions & getLangOpts() const
SelectorTable & Selectors
QualType getObjCProtoType() const
Retrieve the type of the Objective-C Protocol class.
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
QualType getObjCSelType() const
Retrieve the type that corresponds to the predefined Objective-C 'SEL' type.
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
QualType getObjCIdType() const
Represents the Objective-CC id type.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
QualType getObjCClassRedefinitionType() const
Retrieve the type that Class has been defined to, which may be different from the built-in Class if C...
QualType getObjCIdRedefinitionType() const
Retrieve the type that id has been defined to, which may be different from the built-in id if id has ...
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
CharUnits getSize() const
getSize - Get the record size in characters.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Represents a block literal declaration, which is like an unnamed FunctionDecl.
QualType withConst() const
Retrieves a version of this type with const applied.
CharUnits - This is an opaque type for sizes expressed in character units.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
llvm::Type * getElementType() const
Return the type of the values stored in this address.
unsigned getIndex() const
CharUnits getOffset() const
CGBlockInfo - Information to generate a block literal.
const BlockDecl * getBlockDecl() const
llvm::StructType * StructureType
CharUnits BlockHeaderForcedGapOffset
bool NeedsCopyDispose
True if the block has captures that would necessitate custom copy or dispose helper functions if the ...
CharUnits BlockHeaderForcedGapSize
const Capture & getCapture(const VarDecl *var) const
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
llvm::Value * CreateIsNull(Address Addr, const Twine &Name="")
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Address CreateStructGEP(Address Addr, unsigned Index, const llvm::Twine &Name="")
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::LoadInst * CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, CharUnits Align, const llvm::Twine &Name="")
All available information about a concrete callee.
static CGCallee forDirect(llvm::Constant *functionPtr, const CGCalleeInfo &abstractInfo=CGCalleeInfo())
Implements runtime-specific code generation functions.
virtual llvm::Constant * BuildByrefLayout(CodeGen::CodeGenModule &CGM, QualType T)=0
Returns an i8* which points to the byref layout information.
static void destroyCalleeDestroyedArguments(CodeGenFunction &CGF, const ObjCMethodDecl *method, const CallArgList &callArgs)
Destroy the callee-destroyed arguments of the given method, if it has any.
virtual llvm::Function * GenerateMethod(const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD)=0
Generate a function preamble for a method with the specified types.
virtual std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM, const CGBlockInfo &blockInfo)
virtual llvm::Constant * BuildGCBlockLayout(CodeGen::CodeGenModule &CGM, const CodeGen::CGBlockInfo &blockInfo)=0
virtual ConstantAddress GenerateConstantString(const StringLiteral *)=0
Generate a constant string object.
virtual void GenerateProtocol(const ObjCProtocolDecl *OPD)=0
Generate the named protocol.
virtual llvm::Constant * BuildRCBlockLayout(CodeGen::CodeGenModule &CGM, const CodeGen::CGBlockInfo &blockInfo)=0
virtual void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn, const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD)=0
Generates prologue for direct Objective-C Methods.
CallArgList - Type for representing both the value and type of arguments in a call.
void add(RValue rvalue, QualType type)
void addFrom(const CallArgList &other)
Add all the arguments from another CallArgList to this one.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
llvm::Value * EmitFromMemory(llvm::Value *Value, QualType Ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
void EmitAutoVarDecl(const VarDecl &D)
EmitAutoVarDecl - Emit an auto variable declaration.
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
SmallVector< llvm::Value *, 8 > ObjCEHValueStack
ObjCEHValueStack - Stack of Objective-C exception values, used for rethrows.
llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)
CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **callOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
RawAddress getNormalCleanupDestSlot()
JumpDest ReturnBlock
ReturnBlock - Unified return block.
llvm::Value * EmitObjCThrowOperand(const Expr *expr)
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
void PopCleanupBlock(bool FallThroughIsBranchThrough=false, bool ForDeactivation=false)
PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::Type * ConvertType(QualType T)
RawAddress NormalCleanupDest
i32s containing the indexes of the cleanup destinations.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs=std::nullopt)
EmitStmt - Emit the code for the statement.
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
llvm::LLVMContext & getLLVMContext()
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
This class organizes the cross-function state that is used while generating LLVM code.
llvm::Module & getModule() const
llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)
Create or return a runtime function declaration with the specified type and name.
void addCompilerUsedGlobal(llvm::GlobalValue *GV)
Add a global to a list to be added to the llvm.compiler.used metadata.
llvm::Constant * GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH=false)
Get the address of the RTTI descriptor for the given type.
bool ReturnTypeUsesFPRet(QualType ResultType)
Return true iff the given type uses 'fpret' when used as a return type.
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const TargetInfo & getTarget() const
const llvm::DataLayout & getDataLayout() const
bool ReturnTypeUsesFP2Ret(QualType ResultType)
Return true iff the given type uses 'fp2ret' when used as a return type.
const llvm::Triple & getTriple() const
bool ReturnSlotInterferesWithArgs(const CGFunctionInfo &FI)
Return true iff the given type uses an argument slot when 'sret' is used as a return type.
llvm::Constant * CreateRuntimeVariable(llvm::Type *Ty, StringRef Name)
Create a new runtime global variable with the specified type and name.
ConstantAddress GetAddrOfConstantCFString(const StringLiteral *Literal)
Return a pointer to a constant CFString object for the given string.
ASTContext & getContext() const
bool ReturnTypeUsesSRet(const CGFunctionInfo &FI)
Return true iff the given type uses 'sret' when used as a return type.
llvm::LLVMContext & getLLVMContext()
llvm::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
ConstantAddress GetAddrOfConstantCString(const std::string &Str, const char *GlobalName=nullptr)
Returns a pointer to a character array containing the literal and a terminating '\0' character.
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
A specialization of Address that requires the address to be an LLVM Constant.
llvm::Constant * getPointer() const
StructBuilder beginStruct(llvm::StructType *ty=nullptr)
A helper class of ConstantInitBuilder, used for building constant array initializers.
The standard implementation of ConstantInitBuilder used in Clang.
A helper class of ConstantInitBuilder, used for building constant struct initializers.
Information for lazily generating a cleanup.
LValue - This represents an lvalue references.
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
Address getAggregateAddress() const
getAggregateAddr() - Return the Value* of the address of the aggregate.
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
An abstract representation of an aligned address.
llvm::Value * getPointer() const
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
Decl - This represents one declaration (or definition), e.g.
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
This represents one expression.
Represents a member of a struct/union/class.
bool isBitField() const
Determines whether this field is a bitfield.
unsigned getBitWidthValue(const ASTContext &Ctx) const
Computes the bit width of this field, if this is a bit field.
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
clang::ObjCRuntime ObjCRuntime
std::string ObjCConstantStringClass
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Represents Objective-C's @catch statement.
Represents Objective-C's @finally statement.
Represents Objective-C's @synchronized statement.
Represents Objective-C's @throw statement.
Represents Objective-C's @try ... @catch ... @finally statement.
const ObjCAtFinallyStmt * getFinallyStmt() const
Retrieve the @finally statement, if any.
catch_range catch_stmts()
ObjCCategoryDecl - Represents a category declaration.
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration.
ObjCCompatibleAliasDecl - Represents alias of a class.
ObjCContainerDecl - Represents a container for method declarations.
method_range methods() const
prop_range properties() const
const ObjCInterfaceDecl * getClassInterface() const
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Represents an ObjC class declaration.
ObjCIvarDecl * all_declared_ivar_begin()
all_declared_ivar_begin - return first ivar declared in this class, its extensions and its implementa...
StringRef getObjCRuntimeNameAsString() const
Produce a name to be used for class's metadata.
ObjCInterfaceDecl * getSuperClass() const
bool isSuperClassOf(const ObjCInterfaceDecl *I) const
isSuperClassOf - Return true if this class is the specified class or is a super class of the specifie...
ObjCIvarDecl - Represents an ObjC instance variable.
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
ObjCIvarDecl * getNextIvar()
ObjCMethodDecl - Represents an instance or class method declaration.
ImplicitParamDecl * getSelfDecl() const
bool hasParamDestroyedInCallee() const
True if the method has a parameter that's destroyed in the callee.
Stmt * getBody() const override
Retrieve the body of this method, if it has one.
ObjCMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
bool isDirectMethod() const
True if the method is tagged as objc_direct.
Selector getSelector() const
ImplicitParamDecl * getCmdDecl() const
QualType getReturnType() const
bool isClassMethod() const
ObjCInterfaceDecl * getClassInterface()
Represents a pointer to an Objective C object.
bool isObjCQualifiedIdType() const
True if this is equivalent to 'id.
const ObjCObjectType * getObjectType() const
Gets the type pointed to by this ObjC pointer.
bool isObjCIdType() const
True if this is equivalent to the 'id' type, i.e.
Represents a class type in Objective C.
ObjCInterfaceDecl * getInterface() const
Gets the interface declaration for this object type, if the base type really is an interface.
Represents one property declaration in an Objective-C interface.
Represents an Objective-C protocol declaration.
ObjCProtocolDecl * getDefinition()
Retrieve the definition of this protocol, if any.
StringRef getObjCRuntimeNameAsString() const
Produce a name to be used for protocol's metadata.
ObjCProtocolList::iterator protocol_iterator
protocol_iterator protocol_begin() const
protocol_range protocols() const
protocol_iterator protocol_end() const
bool isNonFragile() const
Does this runtime follow the set of implied behaviors for a "non-fragile" ABI?
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
bool isObjCGCStrong() const
true when Type is objc's strong.
bool isObjCGCWeak() const
true when Type is objc's weak.
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
@ OCL_None
There is no lifetime qualification on this type.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
Represents a struct/union/class.
field_range fields() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
Selector getSelector(unsigned NumArgs, const IdentifierInfo **IIV)
Can create any sort of selector.
Smart pointer class that efficiently represents Objective-C method names.
std::string getAsString() const
Derive the full selector name (e.g.
Stmt - This represents one statement.
StringLiteral - This represents a string literal expression, e.g.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
unsigned getCharWidth() const
The base class of the type hierarchy.
bool isBlockPointerType() const
CanQualType getCanonicalTypeUnqualified() const
const T * castAs() const
Member-template castAs<specific type>.
bool isObjCQualifiedIdType() const
bool isObjCIdType() const
bool isObjCObjectPointerType() const
bool isObjCQualifiedClassType() const
bool isObjCClassType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Represents a variable declaration or definition.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Decl, BlockDecl > blockDecl
Matches block declarations.
bool Zero(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
Linkage
Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have.
Selector GetUnarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing an unary selector.
Selector GetNullarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing a nullary selector.
const FunctionProtoType * T
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
@ Class
The "class" keyword introduces the elaborated-type-specifier.
@ HiddenVisibility
Objects with "hidden" visibility are not seen by the dynamic linker.
int printf(__constant const char *st,...) __attribute__((format(printf
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
llvm::CallingConv::ID getRuntimeCC() const
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::IntegerType * IntTy
int
llvm::PointerType * Int8PtrTy
llvm::PointerType * UnqualPtrTy
llvm::IntegerType * PtrDiffTy
CharUnits getPointerAlign() const