29#include "llvm/ADT/CachedHashString.h"
30#include "llvm/ADT/DenseSet.h"
31#include "llvm/ADT/SetVector.h"
32#include "llvm/ADT/SmallPtrSet.h"
33#include "llvm/ADT/SmallString.h"
34#include "llvm/IR/DataLayout.h"
35#include "llvm/IR/InlineAsm.h"
36#include "llvm/IR/IntrinsicInst.h"
37#include "llvm/IR/LLVMContext.h"
38#include "llvm/IR/Module.h"
39#include "llvm/Support/ScopedPrinter.h"
40#include "llvm/Support/raw_ostream.h"
44using namespace CodeGen;
51class ObjCCommonTypesHelper {
53 llvm::LLVMContext &VMContext;
63 llvm::FunctionCallee getMessageSendFn()
const {
66 llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy};
67 return CGM.CreateRuntimeFunction(
68 llvm::FunctionType::get(ObjectPtrTy, params,
true),
"objc_msgSend",
69 llvm::AttributeList::get(CGM.getLLVMContext(),
70 llvm::AttributeList::FunctionIndex,
71 llvm::Attribute::NonLazyBind));
79 llvm::FunctionCallee getMessageSendStretFn()
const {
80 llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy};
81 return CGM.CreateRuntimeFunction(
82 llvm::FunctionType::get(CGM.VoidTy, params,
true),
83 "objc_msgSend_stret");
91 llvm::FunctionCallee getMessageSendFpretFn()
const {
92 llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy};
93 return CGM.CreateRuntimeFunction(
94 llvm::FunctionType::get(CGM.DoubleTy, params,
true),
95 "objc_msgSend_fpret");
103 llvm::FunctionCallee getMessageSendFp2retFn()
const {
104 llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy};
105 llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
106 llvm::Type *resultType =
107 llvm::StructType::get(longDoubleType, longDoubleType);
109 return CGM.CreateRuntimeFunction(
110 llvm::FunctionType::get(resultType, params,
true),
111 "objc_msgSend_fp2ret");
119 llvm::FunctionCallee getMessageSendSuperFn()
const {
120 llvm::Type *params[] = {SuperPtrTy, SelectorPtrTy};
121 return CGM.CreateRuntimeFunction(
122 llvm::FunctionType::get(ObjectPtrTy, params,
true),
123 "objc_msgSendSuper");
130 llvm::FunctionCallee getMessageSendSuperFn2()
const {
131 llvm::Type *params[] = {SuperPtrTy, SelectorPtrTy};
132 return CGM.CreateRuntimeFunction(
133 llvm::FunctionType::get(ObjectPtrTy, params,
true),
134 "objc_msgSendSuper2");
141 llvm::FunctionCallee getMessageSendSuperStretFn()
const {
142 llvm::Type *params[] = {Int8PtrTy, SuperPtrTy, SelectorPtrTy};
143 return CGM.CreateRuntimeFunction(
144 llvm::FunctionType::get(CGM.VoidTy, params,
true),
145 "objc_msgSendSuper_stret");
152 llvm::FunctionCallee getMessageSendSuperStretFn2()
const {
153 llvm::Type *params[] = {Int8PtrTy, SuperPtrTy, SelectorPtrTy};
154 return CGM.CreateRuntimeFunction(
155 llvm::FunctionType::get(CGM.VoidTy, params,
true),
156 "objc_msgSendSuper2_stret");
159 llvm::FunctionCallee getMessageSendSuperFpretFn()
const {
161 return getMessageSendSuperFn();
164 llvm::FunctionCallee getMessageSendSuperFpretFn2()
const {
166 return getMessageSendSuperFn2();
173 llvm::IntegerType *ShortTy, *IntTy, *LongTy;
174 llvm::PointerType *Int8PtrTy, *Int8PtrPtrTy;
175 llvm::PointerType *Int8PtrProgramASTy;
176 llvm::Type *IvarOffsetVarTy;
179 llvm::PointerType *ObjectPtrTy;
182 llvm::PointerType *PtrObjectPtrTy;
185 llvm::PointerType *SelectorPtrTy;
193 llvm::StructType *SuperTy;
195 llvm::PointerType *SuperPtrTy;
199 llvm::StructType *PropertyTy;
203 llvm::StructType *PropertyListTy;
205 llvm::PointerType *PropertyListPtrTy;
208 llvm::StructType *MethodTy;
213 llvm::PointerType *CachePtrTy;
215 llvm::FunctionCallee getGetPropertyFn() {
224 llvm::FunctionType *FTy = Types.GetFunctionType(
225 Types.arrangeBuiltinFunctionDeclaration(IdType, Params));
229 llvm::FunctionCallee getSetPropertyFn() {
242 llvm::FunctionType *FTy = Types.GetFunctionType(
243 Types.arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Params));
247 llvm::FunctionCallee getOptimizedSetPropertyFn(
bool atomic,
bool copy) {
262 Params.push_back(IdType);
263 Params.push_back(SelType);
264 Params.push_back(IdType);
266 llvm::FunctionType *FTy = Types.GetFunctionType(
267 Types.arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Params));
270 name =
"objc_setProperty_atomic_copy";
271 else if (atomic && !copy)
272 name =
"objc_setProperty_atomic";
273 else if (!atomic && copy)
274 name =
"objc_setProperty_nonatomic_copy";
276 name =
"objc_setProperty_nonatomic";
281 llvm::FunctionCallee getCopyStructFn() {
289 Params.push_back(Ctx.
BoolTy);
290 Params.push_back(Ctx.
BoolTy);
291 llvm::FunctionType *FTy = Types.GetFunctionType(
292 Types.arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Params));
300 llvm::FunctionCallee getCppAtomicObjectFunction() {
309 llvm::FunctionType *FTy = Types.GetFunctionType(
310 Types.arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Params));
314 llvm::FunctionCallee getEnumerationMutationFn() {
320 llvm::FunctionType *FTy = Types.GetFunctionType(
321 Types.arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Params));
325 llvm::FunctionCallee getLookUpClassFn() {
332 llvm::FunctionType *FTy =
333 Types.GetFunctionType(Types.arrangeBuiltinFunctionDeclaration(
339 llvm::FunctionCallee getGcReadWeakFn() {
342 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
347 llvm::FunctionCallee getGcAssignWeakFn() {
349 llvm::Type *args[] = {ObjectPtrTy, CGM.
UnqualPtrTy};
350 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
355 llvm::FunctionCallee getGcAssignGlobalFn() {
357 llvm::Type *args[] = {ObjectPtrTy, CGM.
UnqualPtrTy};
358 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
363 llvm::FunctionCallee getGcAssignThreadLocalFn() {
365 llvm::Type *args[] = {ObjectPtrTy, CGM.
UnqualPtrTy};
366 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
371 llvm::FunctionCallee getGcAssignIvarFn() {
374 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
379 llvm::FunctionCallee GcMemmoveCollectableFn() {
381 llvm::Type *args[] = {Int8PtrTy, Int8PtrTy, LongTy};
382 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args,
false);
387 llvm::FunctionCallee getGcAssignStrongCastFn() {
389 llvm::Type *args[] = {ObjectPtrTy, CGM.
UnqualPtrTy};
390 llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args,
false);
395 llvm::FunctionCallee getExceptionThrowFn() {
397 llvm::Type *args[] = {ObjectPtrTy};
398 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.
VoidTy, args,
false);
403 llvm::FunctionCallee getExceptionRethrowFn() {
405 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.
VoidTy,
false);
410 llvm::FunctionCallee getSyncEnterFn() {
412 llvm::Type *args[] = {ObjectPtrTy};
413 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.
IntTy, args,
false);
418 llvm::FunctionCallee getSyncExitFn() {
420 llvm::Type *args[] = {ObjectPtrTy};
421 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.
IntTy, args,
false);
425 llvm::FunctionCallee getSendFn(
bool IsSuper)
const {
426 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
429 llvm::FunctionCallee getSendFn2(
bool IsSuper)
const {
430 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
433 llvm::FunctionCallee getSendStretFn(
bool IsSuper)
const {
434 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
437 llvm::FunctionCallee getSendStretFn2(
bool IsSuper)
const {
438 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
441 llvm::FunctionCallee getSendFpretFn(
bool IsSuper)
const {
442 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
445 llvm::FunctionCallee getSendFpretFn2(
bool IsSuper)
const {
446 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
449 llvm::FunctionCallee getSendFp2retFn(
bool IsSuper)
const {
450 return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
453 llvm::FunctionCallee getSendFp2RetFn2(
bool IsSuper)
const {
454 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
462class ObjCTypesHelper :
public ObjCCommonTypesHelper {
465 llvm::StructType *SymtabTy;
467 llvm::PointerType *SymtabPtrTy;
469 llvm::StructType *ModuleTy;
472 llvm::StructType *ProtocolTy;
474 llvm::PointerType *ProtocolPtrTy;
477 llvm::StructType *ProtocolExtensionTy;
480 llvm::PointerType *ProtocolExtensionPtrTy;
483 llvm::StructType *MethodDescriptionTy;
486 llvm::StructType *MethodDescriptionListTy;
489 llvm::PointerType *MethodDescriptionListPtrTy;
491 llvm::StructType *ProtocolListTy;
493 llvm::PointerType *ProtocolListPtrTy;
495 llvm::StructType *CategoryTy;
497 llvm::StructType *ClassTy;
499 llvm::PointerType *ClassPtrTy;
501 llvm::StructType *ClassExtensionTy;
503 llvm::PointerType *ClassExtensionPtrTy;
505 llvm::StructType *IvarTy;
507 llvm::StructType *IvarListTy;
509 llvm::PointerType *IvarListPtrTy;
511 llvm::StructType *MethodListTy;
513 llvm::PointerType *MethodListPtrTy;
516 llvm::StructType *ExceptionDataTy;
519 llvm::FunctionCallee getExceptionTryEnterFn() {
522 llvm::FunctionType::get(CGM.
VoidTy, params,
false),
523 "objc_exception_try_enter");
527 llvm::FunctionCallee getExceptionTryExitFn() {
530 llvm::FunctionType::get(CGM.
VoidTy, params,
false),
531 "objc_exception_try_exit");
535 llvm::FunctionCallee getExceptionExtractFn() {
538 llvm::FunctionType::get(ObjectPtrTy, params,
false),
539 "objc_exception_extract");
543 llvm::FunctionCallee getExceptionMatchFn() {
544 llvm::Type *params[] = {ClassPtrTy, ObjectPtrTy};
546 llvm::FunctionType::get(CGM.
Int32Ty, params,
false),
547 "objc_exception_match");
551 llvm::FunctionCallee getSetJmpFn() {
555 llvm::FunctionType::get(CGM.
Int32Ty, params,
false),
"_setjmp",
557 llvm::AttributeList::FunctionIndex,
558 llvm::Attribute::NonLazyBind));
567class ObjCNonFragileABITypesHelper :
public ObjCCommonTypesHelper {
570 llvm::StructType *MethodListnfABITy;
573 llvm::PointerType *MethodListnfABIPtrTy;
576 llvm::StructType *ProtocolnfABITy;
579 llvm::PointerType *ProtocolnfABIPtrTy;
582 llvm::StructType *ProtocolListnfABITy;
585 llvm::PointerType *ProtocolListnfABIPtrTy;
588 llvm::StructType *ClassnfABITy;
591 llvm::PointerType *ClassnfABIPtrTy;
594 llvm::StructType *IvarnfABITy;
597 llvm::StructType *IvarListnfABITy;
600 llvm::PointerType *IvarListnfABIPtrTy;
603 llvm::StructType *ClassRonfABITy;
606 llvm::PointerType *ImpnfABITy;
609 llvm::StructType *CategorynfABITy;
618 llvm::StructType *MessageRefTy;
623 llvm::Type *MessageRefPtrTy;
632 llvm::StructType *SuperMessageRefTy;
635 llvm::PointerType *SuperMessageRefPtrTy;
637 llvm::FunctionCallee getMessageSendFixupFn() {
639 llvm::Type *params[] = {ObjectPtrTy, MessageRefPtrTy};
641 llvm::FunctionType::get(ObjectPtrTy, params,
true),
642 "objc_msgSend_fixup");
645 llvm::FunctionCallee getMessageSendFpretFixupFn() {
647 llvm::Type *params[] = {ObjectPtrTy, MessageRefPtrTy};
649 llvm::FunctionType::get(ObjectPtrTy, params,
true),
650 "objc_msgSend_fpret_fixup");
653 llvm::FunctionCallee getMessageSendStretFixupFn() {
655 llvm::Type *params[] = {ObjectPtrTy, MessageRefPtrTy};
657 llvm::FunctionType::get(ObjectPtrTy, params,
true),
658 "objc_msgSend_stret_fixup");
661 llvm::FunctionCallee getMessageSendSuper2FixupFn() {
664 llvm::Type *params[] = {SuperPtrTy, SuperMessageRefPtrTy};
666 llvm::FunctionType::get(ObjectPtrTy, params,
true),
667 "objc_msgSendSuper2_fixup");
670 llvm::FunctionCallee getMessageSendSuper2StretFixupFn() {
673 llvm::Type *params[] = {SuperPtrTy, SuperMessageRefPtrTy};
675 llvm::FunctionType::get(ObjectPtrTy, params,
true),
676 "objc_msgSendSuper2_stret_fixup");
679 llvm::FunctionCallee getObjCEndCatchFn() {
684 llvm::FunctionCallee getObjCBeginCatchFn() {
685 llvm::Type *params[] = {Int8PtrTy};
687 llvm::FunctionType::get(Int8PtrTy, params,
false),
"objc_begin_catch");
695 llvm::FunctionCallee getLoadClassrefFn()
const {
701 llvm::Type *params[] = {Int8PtrPtrTy};
703 llvm::AttributeSet AS = llvm::AttributeSet::get(
705 llvm::Attribute::get(
C, llvm::Attribute::NonLazyBind),
706 llvm::Attribute::getWithMemoryEffects(
707 C, llvm::MemoryEffects::none()),
708 llvm::Attribute::get(
C, llvm::Attribute::NoUnwind),
711 llvm::FunctionType::get(ClassnfABIPtrTy, params,
false),
714 llvm::AttributeList::FunctionIndex, AS));
715 if (!CGM.
getTriple().isOSBinFormatCOFF())
716 cast<llvm::Function>(F.getCallee())
717 ->setLinkage(llvm::Function::ExternalWeakLinkage);
722 llvm::StructType *EHTypeTy;
723 llvm::Type *EHTypePtrTy;
728enum class ObjCLabelType {
741 SKIP_SCAN(
unsigned _skip = 0,
unsigned _scan = 0)
742 : skip(_skip), scan(_scan) {}
750 enum BLOCK_LAYOUT_OPCODE {
757 BLOCK_LAYOUT_OPERATOR = 0,
763 BLOCK_LAYOUT_NON_OBJECT_BYTES = 1,
768 BLOCK_LAYOUT_NON_OBJECT_WORDS = 2,
772 BLOCK_LAYOUT_STRONG = 3,
775 BLOCK_LAYOUT_BYREF = 4,
779 BLOCK_LAYOUT_WEAK = 5,
783 BLOCK_LAYOUT_UNRETAINED = 6
801 enum BLOCK_LAYOUT_OPCODE opcode;
804 RUN_SKIP(
enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
807 : opcode(
Opcode), block_var_bytepos(BytePos), block_var_size(
Size) {}
811 return block_var_bytepos <
b.block_var_bytepos;
816 llvm::LLVMContext &VMContext;
825 llvm::SetVector<IdentifierInfo *> LazySymbols;
831 llvm::SetVector<IdentifierInfo *> DefinedSymbols;
834 llvm::StringMap<llvm::GlobalVariable *> ClassNames;
837 llvm::DenseMap<Selector, llvm::GlobalVariable *> MethodVarNames;
844 llvm::StringMap<llvm::GlobalVariable *> MethodVarTypes;
848 llvm::DenseMap<const ObjCMethodDecl *, llvm::Function *> MethodDefinitions;
852 llvm::DenseMap<const ObjCMethodDecl *, llvm::Function *>
853 DirectMethodDefinitions;
856 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> PropertyNames;
859 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> ClassReferences;
862 llvm::DenseMap<Selector, llvm::GlobalVariable *> SelectorReferences;
867 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> Protocols;
871 llvm::DenseSet<IdentifierInfo *> DefinedProtocols;
893 llvm::WeakTrackingVH ConstantStringClassRef;
896 llvm::StructType *NSConstantStringType =
nullptr;
898 llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap;
902 llvm::Constant *GetMethodVarName(
Selector Sel);
910 bool Extended =
false);
911 llvm::Constant *GetMethodVarType(
const FieldDecl *
D);
919 const Decl *Container);
924 llvm::Constant *GetClassName(StringRef RuntimeName);
942 return BuildIvarLayout(OI, beginOffset, endOffset,
true,
false);
949 return BuildIvarLayout(OI, beginOffset, endOffset,
false,
hasMRCWeakIvars);
959 bool &HasUnion,
bool ByrefLayout =
false);
961 void BuildRCRecordLayout(
const llvm::StructLayout *RecLayout,
964 CharUnits BytePos,
bool &HasUnion,
bool ByrefLayout);
968 llvm::Constant *getBitmapBlockLayout(
bool ComputeByrefLayout);
973 const ObjCCommonTypesHelper &ObjCTypes);
977 llvm::Constant *EmitPropertyList(Twine Name,
const Decl *Container,
979 const ObjCCommonTypesHelper &ObjCTypes,
980 bool IsClassProperty);
986 const ObjCCommonTypesHelper &ObjCTypes);
997 ObjCCommonTypesHelper &ObjCTypes);
999 std::string GetSectionName(StringRef Section, StringRef MachOAttributes);
1016 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
1020 llvm::GlobalVariable *CreateMetadataVar(Twine Name, llvm::Constant *
Init,
1024 llvm::GlobalVariable *CreateCStringLiteral(StringRef Name,
1025 ObjCLabelType LabelType,
1026 bool ForceNonFragileABI =
false,
1027 bool NullTerminate =
true);
1037 const ObjCCommonTypesHelper &ObjCTypes);
1041 void EmitImageInfo();
1047 bool isNonFragileABI()
const {
return ObjCABI == 2; }
1069 virtual llvm::Constant *GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD) = 0;
1071 virtual llvm::Constant *getNSConstantStringClassRef() = 0;
1089enum class MethodListType {
1090 CategoryInstanceMethods,
1091 CategoryClassMethods,
1094 ProtocolInstanceMethods,
1095 ProtocolClassMethods,
1096 OptionalProtocolInstanceMethods,
1097 OptionalProtocolClassMethods,
1102class ProtocolMethodLists {
1105 RequiredInstanceMethods,
1106 RequiredClassMethods,
1107 OptionalInstanceMethods,
1108 OptionalClassMethods
1110 enum { NumProtocolMethodLists = 4 };
1112 static MethodListType getMethodListKind(Kind kind) {
1114 case RequiredInstanceMethods:
1115 return MethodListType::ProtocolInstanceMethods;
1116 case RequiredClassMethods:
1117 return MethodListType::ProtocolClassMethods;
1118 case OptionalInstanceMethods:
1119 return MethodListType::OptionalProtocolInstanceMethods;
1120 case OptionalClassMethods:
1121 return MethodListType::OptionalProtocolClassMethods;
1123 llvm_unreachable(
"bad kind");
1129 ProtocolMethodLists result;
1131 for (
auto *MD : PD->
methods()) {
1133 (2 *
size_t(MD->isOptional())) + (
size_t(MD->isClassMethod()));
1134 result.Methods[index].push_back(MD);
1140 template <
class Self>
1151 for (
auto &list : Methods) {
1152 for (
auto MD : list) {
1153 result.push_back(self->GetMethodVarType(MD,
true));
1160 template <
class Self>
1164 getMethodListKind(kind), Methods[kind]);
1170class CGObjCMac :
public CGObjCCommonMac {
1172 friend ProtocolMethodLists;
1174 ObjCTypesHelper ObjCTypes;
1178 void EmitModuleInfo();
1182 llvm::Constant *EmitModuleSymbols();
1186 void FinishModule();
1201 llvm::Value *EmitNSAutoreleasePoolClassRef(
CodeGenFunction &CGF)
override;
1221 llvm::Constant *Protocols,
1232 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1251 const ProtocolMethodLists &methodLists);
1255 llvm::Constant *EmitProtocolList(Twine Name,
1267 llvm::Constant *getNSConstantStringClassRef()
override;
1269 llvm::Function *ModuleInitFunction()
override;
1274 llvm::Value *Receiver,
1282 bool isCategoryImpl, llvm::Value *Receiver,
bool IsClassMessage,
1296 llvm::Constant *GetEHType(
QualType T)
override;
1307 llvm::FunctionCallee GetPropertyGetFunction()
override;
1308 llvm::FunctionCallee GetPropertySetFunction()
override;
1309 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
1310 bool copy)
override;
1311 llvm::FunctionCallee GetGetStructFunction()
override;
1312 llvm::FunctionCallee GetSetStructFunction()
override;
1313 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override;
1314 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override;
1315 llvm::FunctionCallee EnumerationMutationFunction()
override;
1323 bool ClearInsertionPoint =
true)
override;
1325 Address AddrWeakObj)
override;
1329 Address dest,
bool threadlocal =
false)
override;
1331 Address dest, llvm::Value *ivarOffset)
override;
1335 Address src, llvm::Value *size)
override;
1339 unsigned CVRQualifiers)
override;
1345class CGObjCNonFragileABIMac :
public CGObjCCommonMac {
1347 friend ProtocolMethodLists;
1348 ObjCNonFragileABITypesHelper ObjCTypes;
1349 llvm::GlobalVariable *ObjCEmptyCacheVar;
1350 llvm::Constant *ObjCEmptyVtableVar;
1353 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> SuperClassReferences;
1356 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> MetaClassReferences;
1359 llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> EHTypeReferences;
1363 llvm::DenseSet<Selector> VTableDispatchMethods;
1366 std::vector<llvm::GlobalValue *> DefinedMetaClasses;
1370 bool isVTableDispatchedSelector(
Selector Sel);
1374 void FinishNonFragileABIModule();
1379 StringRef SymbolName, StringRef SectionName);
1381 llvm::GlobalVariable *
1382 BuildClassRoTInitializer(
unsigned flags,
unsigned InstanceStart,
1383 unsigned InstanceSize,
1385 llvm::GlobalVariable *
1387 llvm::Constant *IsAGV, llvm::Constant *SuperClassGV,
1395 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1407 unsigned long int offset);
1422 llvm::Constant *EmitProtocolList(Twine Name,
1433 llvm::Constant *GetClassGlobal(StringRef Name,
1435 bool Weak =
false,
bool DLLImport =
false);
1443 llvm::GlobalVariable *Entry);
1452 llvm::Value *EmitNSAutoreleasePoolClassRef(
CodeGenFunction &CGF)
override;
1480 StringRef getMetaclassSymbolPrefix()
const {
return "OBJC_METACLASS_$_"; }
1482 StringRef getClassSymbolPrefix()
const {
return "OBJC_CLASS_$_"; }
1485 uint32_t &InstanceStart, uint32_t &InstanceSize);
1500 bool ImplementationIsNonLazy(
const ObjCImplDecl *OD)
const;
1519 dyn_cast_or_null<ObjCMethodDecl>(CGF.
CurFuncDecl))
1520 if (MD->isInstanceMethod() && !MD->isDirectMethod())
1529 assert(ID !=
nullptr &&
"Passed a null class to check layout");
1530 for (;
ID !=
nullptr;
ID =
ID->getSuperClass()) {
1533 if (
ID->getIdentifier()->getName() ==
"NSObject")
1538 if (!
ID->getImplementation())
1549 llvm::Constant *getNSConstantStringClassRef()
override;
1551 llvm::Function *ModuleInitFunction()
override;
1556 llvm::Value *Receiver,
1564 bool isCategoryImpl, llvm::Value *Receiver,
bool IsClassMessage,
1571 return EmitSelector(CGF, Sel);
1574 return EmitSelectorAddr(Sel);
1581 return EmitSelector(CGF,
Method->getSelector());
1593 llvm::Constant *GetEHType(
QualType T)
override;
1595 llvm::FunctionCallee GetPropertyGetFunction()
override {
1596 return ObjCTypes.getGetPropertyFn();
1598 llvm::FunctionCallee GetPropertySetFunction()
override {
1599 return ObjCTypes.getSetPropertyFn();
1602 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
1603 bool copy)
override {
1604 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1607 llvm::FunctionCallee GetSetStructFunction()
override {
1608 return ObjCTypes.getCopyStructFn();
1611 llvm::FunctionCallee GetGetStructFunction()
override {
1612 return ObjCTypes.getCopyStructFn();
1615 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override {
1616 return ObjCTypes.getCppAtomicObjectFunction();
1619 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override {
1620 return ObjCTypes.getCppAtomicObjectFunction();
1623 llvm::FunctionCallee EnumerationMutationFunction()
override {
1624 return ObjCTypes.getEnumerationMutationFn();
1632 bool ClearInsertionPoint =
true)
override;
1634 Address AddrWeakObj)
override;
1638 Address dest,
bool threadlocal =
false)
override;
1640 Address dest, llvm::Value *ivarOffset)
override;
1644 Address src, llvm::Value *size)
override;
1647 unsigned CVRQualifiers)
override;
1655struct NullReturnState {
1656 llvm::BasicBlock *NullBB =
nullptr;
1657 NullReturnState() =
default;
1670 CGF.
Builder.CreateCondBr(isNull, NullBB, callBB);
1687 llvm::BasicBlock *contBB =
nullptr;
1690 llvm::BasicBlock *callBB = CGF.
Builder.GetInsertBlock();
1705 assert(CGF.
Builder.GetInsertBlock() == NullBB);
1727 llvm::PHINode *phi = CGF.
Builder.CreatePHI(null->getType(), 2);
1729 phi->addIncoming(null, NullBB);
1738 assert(result.
isAggregate() &&
"null init of non-aggregate result?");
1751 llvm::Type *scalarTy = callResult.first->getType();
1752 llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
1755 llvm::PHINode *real = CGF.
Builder.CreatePHI(scalarTy, 2);
1756 real->addIncoming(callResult.first, callBB);
1757 real->addIncoming(scalarZero, NullBB);
1758 llvm::PHINode *imag = CGF.
Builder.CreatePHI(scalarTy, 2);
1759 imag->addIncoming(callResult.second, callBB);
1760 imag->addIncoming(scalarZero, NullBB);
1771 llvm::GlobalVariable *
C,
unsigned idx0,
1773 llvm::Value *Idxs[] = {
1774 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1775 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)};
1776 return llvm::ConstantExpr::getGetElementPtr(
C->getValueType(),
C, Idxs);
1783 if (OID->
hasAttr<ObjCExceptionAttr>())
1790static llvm::GlobalValue::LinkageTypes
1792 if (CGM.
getTriple().isOSBinFormatMachO() &&
1793 (Section.empty() || Section.starts_with(
"__DATA")))
1794 return llvm::GlobalValue::InternalLinkage;
1795 return llvm::GlobalValue::PrivateLinkage;
1799static llvm::GlobalVariable *
1802 std::string SectionName;
1803 if (CGM.
getTriple().isOSBinFormatMachO())
1804 SectionName =
"__DATA, __objc_const";
1805 auto *GV = Builder.finishAndCreateGlobal(
1808 GV->setSection(SectionName);
1815 : CGObjCCommonMac(cgm), ObjCTypes(cgm) {
1824 return EmitClassRef(CGF, ID);
1829 return EmitSelector(CGF, Sel);
1832 return EmitSelectorAddr(Sel);
1836 return EmitSelector(CGF,
Method->getSelector());
1839llvm::Constant *CGObjCMac::GetEHType(
QualType T) {
1851 llvm_unreachable(
"asking for catch type for ObjC type in fragile runtime");
1874CGObjCCommonMac::GenerateConstantString(
const StringLiteral *SL) {
1877 : GenerateConstantNSString(SL));
1880static llvm::StringMapEntry<llvm::GlobalVariable *> &
1883 StringRef String = Literal->getString();
1884 StringLength = String.size();
1885 return *Map.insert(std::make_pair(String,
nullptr)).first;
1888llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
1889 if (llvm::Value *
V = ConstantStringClassRef)
1890 return cast<llvm::Constant>(
V);
1893 std::string str = StringClass.empty() ?
"_NSConstantStringClassReference"
1894 :
"_" + StringClass +
"ClassReference";
1896 llvm::Type *PTy = llvm::ArrayType::get(CGM.
IntTy, 0);
1898 ConstantStringClassRef = GV;
1902llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
1903 if (llvm::Value *
V = ConstantStringClassRef)
1904 return cast<llvm::Constant>(
V);
1907 std::string str = StringClass.empty() ?
"OBJC_CLASS_$_NSConstantString"
1908 :
"OBJC_CLASS_$_" + StringClass;
1910 ConstantStringClassRef = GV;
1915CGObjCCommonMac::GenerateConstantNSString(
const StringLiteral *Literal) {
1916 unsigned StringLength = 0;
1917 llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
1920 if (
auto *
C = Entry.second)
1925 llvm::Constant *
Class = getNSConstantStringClassRef();
1928 if (!NSConstantStringType) {
1929 NSConstantStringType =
1931 "struct.__builtin_NSString");
1935 auto Fields = Builder.beginStruct(NSConstantStringType);
1938 Fields.addSignedPointer(Class,
1944 llvm::ConstantDataArray::getString(VMContext, Entry.first());
1946 llvm::GlobalValue::LinkageTypes
Linkage = llvm::GlobalValue::PrivateLinkage;
1947 bool isConstant = !CGM.
getLangOpts().WritableStrings;
1949 auto *GV =
new llvm::GlobalVariable(CGM.
getModule(),
C->getType(), isConstant,
1951 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1954 GV->setAlignment(llvm::Align(1));
1958 Fields.addInt(CGM.
IntTy, StringLength);
1962 GV = Fields.finishAndCreateGlobal(
"_unnamed_nsstring_", Alignment,
1964 llvm::GlobalVariable::PrivateLinkage);
1965 const char *NSStringSection =
"__OBJC,__cstring_object,regular,no_dead_strip";
1966 const char *NSStringNonFragileABISection =
1967 "__DATA,__objc_stringobj,regular,no_dead_strip";
1970 ? NSStringNonFragileABISection
1985 llvm::Value *Receiver,
bool IsClassMessage,
1991 llvm::Value *ReceiverAsObject =
1992 CGF.
Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
1997 llvm::Type *ClassTyPtr = llvm::PointerType::getUnqual(VMContext);
1999 if (IsClassMessage) {
2000 if (isCategoryImpl) {
2007 Target = EmitClassRef(CGF,
Class->getSuperClass());
2012 llvm::Constant *MetaClassPtr = EmitMetaClassRef(Class);
2013 llvm::Value *SuperPtr =
2019 }
else if (isCategoryImpl)
2020 Target = EmitClassRef(CGF,
Class->getSuperClass());
2022 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
2029 llvm::Type *ClassTy =
2033 return EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper.
getPointer(),
2034 ObjCTypes.SuperPtrCTy,
true, CallArgs, Method, Class,
2043 return EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
2045 Method, Class, ObjCTypes);
2053 const ObjCCommonTypesHelper &ObjCTypes) {
2056 llvm::Value *SelValue = llvm::UndefValue::get(Types.ConvertType(selTy));
2060 Arg0 = CGF.
Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
2062 if (!Method || !
Method->isDirectMethod())
2067 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
2072 "Result type mismatch!");
2074 bool ReceiverCanBeNull =
2075 canMessageReceiverBeNull(CGF, Method, IsSuper, ClassReceiver, Arg0);
2077 bool RequiresNullCheck =
false;
2078 bool RequiresSelValue =
true;
2080 llvm::FunctionCallee
Fn =
nullptr;
2081 if (Method &&
Method->isDirectMethod()) {
2083 Fn = GenerateDirectMethod(Method,
Method->getClassInterface());
2086 RequiresSelValue =
false;
2088 if (ReceiverCanBeNull)
2089 RequiresNullCheck =
true;
2090 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
2091 : ObjCTypes.getSendStretFn(IsSuper);
2093 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
2094 : ObjCTypes.getSendFpretFn(IsSuper);
2096 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
2097 : ObjCTypes.getSendFp2retFn(IsSuper);
2102 RequiresNullCheck =
true;
2103 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
2104 : ObjCTypes.getSendFn(IsSuper);
2108 llvm::Constant *BitcastFn = cast<llvm::Constant>(
2109 CGF.
Builder.CreateBitCast(
Fn.getCallee(), MSI.MessengerType));
2114 RequiresNullCheck =
false;
2117 if (!RequiresNullCheck && Method &&
Method->hasParamDestroyedInCallee())
2118 RequiresNullCheck =
true;
2120 NullReturnState nullReturn;
2121 if (RequiresNullCheck) {
2122 nullReturn.init(CGF, Arg0);
2126 if (RequiresSelValue) {
2127 SelValue = GetSelector(CGF, Sel);
2131 llvm::CallBase *CallSite;
2134 CGF.
EmitCall(MSI.CallInfo, Callee, Return, ActualArgs, &CallSite);
2138 if (Method &&
Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
2139 CallSite->setDoesNotReturn();
2142 return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs,
2143 RequiresNullCheck ? Method :
nullptr);
2147 bool pointee =
false) {
2161 switch (ownership) {
2169 llvm_unreachable(
"autoreleasing ivar?");
2171 llvm_unreachable(
"known nonzero");
2173 llvm_unreachable(
"bad objc ownership");
2181 if (Ctx.
getLangOpts().getGC() != LangOptions::NonGC) {
2193 IvarInfo(
CharUnits offset, uint64_t sizeInWords)
2194 : Offset(offset), SizeInWords(sizeInWords) {}
2197 bool operator<(
const IvarInfo &other)
const {
return Offset < other.Offset; }
2201class IvarLayoutBuilder {
2212 bool ForStrongLayout;
2215 bool IsDisordered =
false;
2221 CharUnits instanceEnd,
bool forStrongLayout)
2222 : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
2223 ForStrongLayout(forStrongLayout) {}
2227 template <
class Iterator,
class GetOffsetFn>
2228 void visitAggregate(Iterator begin, Iterator end,
CharUnits aggrOffset,
2229 const GetOffsetFn &getOffset);
2237 bool hasBitmapData()
const {
return !IvarsInfo.empty(); }
2239 llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
2243 const unsigned char *
s = buffer.data();
2244 for (
unsigned i = 0, e = buffer.size(); i < e; i++)
2246 printf(
"0x0%x%s",
s[i],
s[i] != 0 ?
", " :
"");
2248 printf(
"0x%x%s",
s[i],
s[i] != 0 ?
", " :
"");
2258 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2259 if (CGM.
getLangOpts().getGC() == LangOptions::NonGC)
2265 builder.visitBlock(blockInfo);
2267 if (!builder.hasBitmapData())
2271 llvm::Constant *
C = builder.buildBitmap(*
this, buffer);
2272 if (CGM.
getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
2273 printf(
"\n block variable layout for block: ");
2274 builder.dump(buffer);
2280void IvarLayoutBuilder::visitBlock(
const CGBlockInfo &blockInfo) {
2293 for (
const auto &CI :
blockDecl->captures()) {
2294 const VarDecl *variable = CI.getVariable();
2307 if (fieldOffset < lastFieldOffset)
2308 IsDisordered =
true;
2309 lastFieldOffset = fieldOffset;
2313 IvarsInfo.push_back(IvarInfo(fieldOffset, 1));
2317 assert(!
type->isArrayType() &&
"array variable should not be caught");
2319 visitRecord(record, fieldOffset);
2328 IvarsInfo.push_back(IvarInfo(fieldOffset, 1));
2337CGObjCCommonMac::getBlockCaptureLifetime(
QualType FQT,
bool ByrefLayout) {
2353void CGObjCCommonMac::UpdateRunSkipBlockVars(
bool IsByref,
2359 RunSkipBlockVars.push_back(
2360 RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset, FieldSize));
2362 RunSkipBlockVars.push_back(
2363 RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset, FieldSize));
2365 RunSkipBlockVars.push_back(
2366 RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset, FieldSize));
2368 RunSkipBlockVars.push_back(
2369 RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset, FieldSize));
2371 RunSkipBlockVars.push_back(
2372 RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES, FieldOffset, FieldSize));
2375void CGObjCCommonMac::BuildRCRecordLayout(
const llvm::StructLayout *RecLayout,
2380 bool IsUnion = (RD && RD->
isUnion());
2383 const FieldDecl *LastFieldBitfieldOrUnnamed =
nullptr;
2387 if (RecFields.empty())
2391 for (
unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2400 if (!
Field->getIdentifier() ||
Field->isBitField()) {
2401 LastFieldBitfieldOrUnnamed =
Field;
2402 LastBitfieldOrUnnamedOffset = FieldOffset;
2406 LastFieldBitfieldOrUnnamed =
nullptr;
2413 BytePos + FieldOffset, HasUnion);
2418 auto *CArray = cast<ConstantArrayType>(Array);
2419 uint64_t ElCount = CArray->getZExtSize();
2420 assert(CArray &&
"only array with known element size is supported");
2421 FQT = CArray->getElementType();
2423 auto *CArray = cast<ConstantArrayType>(Array);
2424 ElCount *= CArray->getZExtSize();
2425 FQT = CArray->getElementType();
2428 int OldIndex = RunSkipBlockVars.size() - 1;
2430 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset, HasUnion);
2435 for (
int FirstIndex = RunSkipBlockVars.size() - 1; ElIx < ElCount;
2438 for (
int i = OldIndex + 1; i <= FirstIndex; ++i)
2439 RunSkipBlockVars.push_back(
2440 RUN_SKIP(RunSkipBlockVars[i].opcode,
2441 RunSkipBlockVars[i].block_var_bytepos + Size * ElIx,
2442 RunSkipBlockVars[i].block_var_size));
2450 if (UnionIvarSize > MaxUnionSize) {
2451 MaxUnionSize = UnionIvarSize;
2453 MaxFieldOffset = FieldOffset;
2456 UpdateRunSkipBlockVars(
false, getBlockCaptureLifetime(FQT, ByrefLayout),
2457 BytePos + FieldOffset, FieldSize);
2461 if (LastFieldBitfieldOrUnnamed) {
2462 if (LastFieldBitfieldOrUnnamed->
isBitField()) {
2465 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
2466 ((BitFieldSize % ByteSizeInBits) != 0);
2468 Size += LastBitfieldOrUnnamedOffset;
2469 UpdateRunSkipBlockVars(
2471 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->
getType(),
2473 BytePos + LastBitfieldOrUnnamedOffset, Size);
2476 "Expected unnamed");
2479 LastFieldBitfieldOrUnnamed->
getType());
2480 UpdateRunSkipBlockVars(
2482 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->
getType(),
2484 BytePos + LastBitfieldOrUnnamedOffset, FieldSize);
2489 UpdateRunSkipBlockVars(
2490 false, getBlockCaptureLifetime(MaxField->
getType(), ByrefLayout),
2491 BytePos + MaxFieldOffset, MaxUnionSize);
2494void CGObjCCommonMac::BuildRCBlockVarRecordLayout(
const RecordType *RT,
2501 const llvm::StructLayout *RecLayout =
2502 CGM.
getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
2504 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
2516uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2519 if (Layout.size() <= 3) {
2520 unsigned size = Layout.size();
2521 unsigned strong_word_count = 0, byref_word_count = 0, weak_word_count = 0;
2523 enum BLOCK_LAYOUT_OPCODE opcode;
2527 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2528 if (opcode == BLOCK_LAYOUT_STRONG)
2529 strong_word_count = (inst & 0xF) + 1;
2533 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2534 if (opcode == BLOCK_LAYOUT_BYREF)
2535 byref_word_count = (inst & 0xF) + 1;
2539 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2540 if (opcode == BLOCK_LAYOUT_WEAK)
2541 weak_word_count = (inst & 0xF) + 1;
2548 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2549 if (opcode == BLOCK_LAYOUT_STRONG) {
2550 strong_word_count = (inst & 0xF) + 1;
2552 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2553 if (opcode == BLOCK_LAYOUT_BYREF)
2554 byref_word_count = (inst & 0xF) + 1;
2555 else if (opcode == BLOCK_LAYOUT_WEAK)
2556 weak_word_count = (inst & 0xF) + 1;
2559 }
else if (opcode == BLOCK_LAYOUT_BYREF) {
2560 byref_word_count = (inst & 0xF) + 1;
2562 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2563 if (opcode == BLOCK_LAYOUT_WEAK)
2564 weak_word_count = (inst & 0xF) + 1;
2573 opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2574 if (opcode == BLOCK_LAYOUT_STRONG)
2575 strong_word_count = (inst & 0xF) + 1;
2576 else if (opcode == BLOCK_LAYOUT_BYREF)
2577 byref_word_count = (inst & 0xF) + 1;
2578 else if (opcode == BLOCK_LAYOUT_WEAK)
2579 weak_word_count = (inst & 0xF) + 1;
2591 if (strong_word_count == 16 || byref_word_count == 16 ||
2592 weak_word_count == 16)
2595 unsigned count = (strong_word_count != 0) + (byref_word_count != 0) +
2596 (weak_word_count != 0);
2598 if (size == count) {
2599 if (strong_word_count)
2600 Result = strong_word_count;
2602 if (byref_word_count)
2603 Result += byref_word_count;
2605 if (weak_word_count)
2606 Result += weak_word_count;
2612llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(
bool ComputeByrefLayout) {
2613 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2614 if (RunSkipBlockVars.empty())
2618 unsigned WordSizeInBytes = WordSizeInBits / ByteSizeInBits;
2622 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2625 unsigned size = RunSkipBlockVars.size();
2626 for (
unsigned i = 0; i < size; i++) {
2627 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2628 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2629 CharUnits end_byte_pos = start_byte_pos;
2632 if (opcode == RunSkipBlockVars[j].opcode) {
2633 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2639 end_byte_pos - start_byte_pos + RunSkipBlockVars[j - 1].block_var_size;
2641 CharUnits gap = RunSkipBlockVars[j].block_var_bytepos -
2642 RunSkipBlockVars[j - 1].block_var_bytepos -
2643 RunSkipBlockVars[j - 1].block_var_size;
2644 size_in_bytes += gap;
2647 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2648 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2649 size_in_bytes -= residue_in_bytes;
2650 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2653 unsigned size_in_words = size_in_bytes.
getQuantity() / WordSizeInBytes;
2654 while (size_in_words >= 16) {
2657 unsigned char inst = (opcode << 4) | 0xf;
2658 Layout.push_back(inst);
2659 size_in_words -= 16;
2661 if (size_in_words > 0) {
2664 unsigned char inst = (opcode << 4) | (size_in_words - 1);
2665 Layout.push_back(inst);
2668 unsigned char inst = (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) |
2670 Layout.push_back(inst);
2674 while (!Layout.empty()) {
2675 unsigned char inst = Layout.back();
2676 enum BLOCK_LAYOUT_OPCODE opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2677 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES ||
2678 opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2684 uint64_t Result = InlineLayoutInstruction(Layout);
2688 if (ComputeByrefLayout)
2689 printf(
"\n Inline BYREF variable layout: ");
2691 printf(
"\n Inline block variable layout: ");
2692 printf(
"0x0%" PRIx64
"", Result);
2693 if (
auto numStrong = (Result & 0xF00) >> 8)
2694 printf(
", BL_STRONG:%d", (
int)numStrong);
2695 if (
auto numByref = (Result & 0x0F0) >> 4)
2696 printf(
", BL_BYREF:%d", (
int)numByref);
2697 if (
auto numWeak = (Result & 0x00F) >> 0)
2698 printf(
", BL_WEAK:%d", (
int)numWeak);
2699 printf(
", BL_OPERATOR:0\n");
2701 return llvm::ConstantInt::get(CGM.
IntPtrTy, Result);
2704 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2705 Layout.push_back(inst);
2707 for (
unsigned char C : Layout)
2711 if (ComputeByrefLayout)
2712 printf(
"\n Byref variable layout: ");
2714 printf(
"\n Block variable layout: ");
2715 for (
unsigned i = 0, e = BitMap.size(); i != e; i++) {
2716 unsigned char inst = BitMap[i];
2717 enum BLOCK_LAYOUT_OPCODE opcode = (
enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
2720 case BLOCK_LAYOUT_OPERATOR:
2724 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2725 printf(
"BL_NON_OBJECT_BYTES:");
2727 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2728 printf(
"BL_NON_OBJECT_WORD:");
2730 case BLOCK_LAYOUT_STRONG:
2733 case BLOCK_LAYOUT_BYREF:
2736 case BLOCK_LAYOUT_WEAK:
2739 case BLOCK_LAYOUT_UNRETAINED:
2740 printf(
"BL_UNRETAINED:");
2745 printf(
"%d", (inst & 0xf) + delta);
2753 auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
2761 bool HasCopyDisposeHelpers) {
2763 for (
const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) {
2764 if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) {
2768 }
else if (HasCopyDisposeHelpers) {
2776 case CGObjCCommonMac::BLOCK_LAYOUT_STRONG:
2779 case CGObjCCommonMac::BLOCK_LAYOUT_BYREF:
2782 case CGObjCCommonMac::BLOCK_LAYOUT_WEAK:
2789 Str += llvm::to_string(R.block_var_bytepos.getQuantity());
2790 Str +=
"l" + llvm::to_string(R.block_var_size.getQuantity());
2795void CGObjCCommonMac::fillRunSkipBlockVars(
CodeGenModule &CGM,
2797 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
2799 RunSkipBlockVars.clear();
2800 bool hasUnion =
false;
2804 unsigned WordSizeInBytes = WordSizeInBits / ByteSizeInBits;
2809 const llvm::StructLayout *layout =
2819 for (
const auto &CI :
blockDecl->captures()) {
2820 const VarDecl *variable = CI.getVariable();
2832 assert(!
type->isArrayType() &&
"array variable should not be caught");
2835 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2843 UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(
type,
false),
2844 fieldOffset, fieldSize);
2851 fillRunSkipBlockVars(CGM, blockInfo);
2852 return getBitmapBlockLayout(
false);
2855std::string CGObjCCommonMac::getRCBlockLayoutStr(
CodeGenModule &CGM,
2857 fillRunSkipBlockVars(CGM, blockInfo);
2863 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
2864 assert(!
T->
isArrayType() &&
"__block array variable should not be caught");
2866 RunSkipBlockVars.clear();
2867 bool hasUnion =
false;
2869 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion,
2871 llvm::Constant *Result = getBitmapBlockLayout(
true);
2872 if (isa<llvm::ConstantInt>(Result))
2873 Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.
Int8PtrTy);
2876 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2886 return GetProtocolRef(PD);
2898 GetOrEmitProtocol(PD);
2901llvm::Constant *CGObjCCommonMac::GetProtocolRef(
const ObjCProtocolDecl *PD) {
2903 return GetOrEmitProtocol(PD);
2905 return GetOrEmitProtocolRef(PD);
2911 ObjCCommonTypesHelper &ObjCTypes) {
2912 llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn();
2914 llvm::Value *className = CGF.
CGM
2916 ID->getObjCRuntimeNameAsString()))
2919 className = CGF.
Builder.CreateBitCast(
2921 llvm::CallInst *call = CGF.
Builder.CreateCall(lookUpClassFn, className);
2922 call->setDoesNotThrow();
2939 llvm::GlobalVariable *Entry = Protocols[PD->
getIdentifier()];
2942 if (Entry && Entry->hasInitializer())
2954 auto methodLists = ProtocolMethodLists::get(PD);
2957 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
2958 values.add(EmitProtocolExtension(PD, methodLists));
2960 values.add(EmitProtocolList(
"OBJC_PROTOCOL_REFS_" + PD->
getName(),
2962 values.add(methodLists.emitMethodList(
2963 this, PD, ProtocolMethodLists::RequiredInstanceMethods));
2964 values.add(methodLists.emitMethodList(
2965 this, PD, ProtocolMethodLists::RequiredClassMethods));
2969 assert(Entry->hasPrivateLinkage());
2970 values.finishAndSetAsInitializer(Entry);
2972 Entry = values.finishAndCreateGlobal(
2974 false, llvm::GlobalValue::PrivateLinkage);
2975 Entry->setSection(
"__OBJC,__protocol,regular,no_dead_strip");
2984llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD) {
2985 llvm::GlobalVariable *&Entry = Protocols[PD->
getIdentifier()];
2991 Entry =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ProtocolTy,
2992 false, llvm::GlobalValue::PrivateLinkage,
2993 nullptr,
"OBJC_PROTOCOL_" + PD->
getName());
2994 Entry->setSection(
"__OBJC,__protocol,regular,no_dead_strip");
2996 Entry->setAlignment(llvm::Align(4));
3014 const ProtocolMethodLists &methodLists) {
3015 auto optInstanceMethods = methodLists.emitMethodList(
3016 this, PD, ProtocolMethodLists::OptionalInstanceMethods);
3017 auto optClassMethods = methodLists.emitMethodList(
3018 this, PD, ProtocolMethodLists::OptionalClassMethods);
3020 auto extendedMethodTypes = EmitProtocolMethodTypes(
3021 "OBJC_PROTOCOL_METHOD_TYPES_" + PD->
getName(),
3022 methodLists.emitExtendedTypesArray(
this), ObjCTypes);
3024 auto instanceProperties = EmitPropertyList(
3025 "OBJC_$_PROP_PROTO_LIST_" + PD->
getName(),
nullptr, PD, ObjCTypes,
false);
3026 auto classProperties =
3027 EmitPropertyList(
"OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->
getName(),
nullptr,
3028 PD, ObjCTypes,
true);
3031 if (optInstanceMethods->isNullValue() && optClassMethods->isNullValue() &&
3032 extendedMethodTypes->isNullValue() && instanceProperties->isNullValue() &&
3033 classProperties->isNullValue()) {
3034 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
3038 CGM.
getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
3041 auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
3042 values.addInt(ObjCTypes.IntTy, size);
3043 values.add(optInstanceMethods);
3044 values.add(optClassMethods);
3045 values.add(instanceProperties);
3046 values.add(extendedMethodTypes);
3047 values.add(classProperties);
3050 return CreateMetadataVar(
"_OBJC_PROTOCOLEXT_" + PD->
getName(), values,
3062CGObjCMac::EmitProtocolList(Twine name,
3066 auto PDs = GetRuntimeProtocolList(begin, end);
3068 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
3071 auto values = builder.beginStruct();
3074 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
3077 auto countSlot = values.addPlaceholder();
3079 auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
3080 for (
const auto *Proto : PDs)
3081 refsArray.add(GetProtocolRef(Proto));
3083 auto count = refsArray.size();
3086 refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
3088 refsArray.finishAndAddTo(values);
3089 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
3092 if (CGM.
getTriple().isOSBinFormatMachO())
3093 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3095 llvm::GlobalVariable *GV =
3096 CreateMetadataVar(name, values, section, CGM.
getPointerAlign(),
false);
3105 if (IsClassProperty != PD->isClassProperty())
3109 Properties.push_back(PD);
3128llvm::Constant *CGObjCCommonMac::EmitPropertyList(
3130 const ObjCCommonTypesHelper &ObjCTypes,
bool IsClassProperty) {
3131 if (IsClassProperty) {
3135 if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
3136 (Triple.isiOS() && Triple.isOSVersionLT(9)))
3137 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3145 for (
auto *PD : ClassExt->properties()) {
3146 if (IsClassProperty != PD->isClassProperty())
3148 if (PD->isDirectProperty())
3151 Properties.push_back(PD);
3155 if (IsClassProperty != PD->isClassProperty())
3161 if (PD->isDirectProperty())
3163 Properties.push_back(PD);
3167 for (
const auto *
P : OID->all_referenced_protocols())
3170 for (
const auto *
P : CD->protocols())
3175 if (Properties.empty())
3176 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3178 unsigned propertySize =
3182 auto values = builder.beginStruct();
3183 values.addInt(ObjCTypes.IntTy, propertySize);
3184 values.addInt(ObjCTypes.IntTy, Properties.size());
3185 auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
3186 for (
auto PD : Properties) {
3187 auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
3189 property.add(GetPropertyTypeString(PD, Container));
3190 property.finishAndAddTo(propertiesArray);
3192 propertiesArray.finishAndAddTo(values);
3195 if (CGM.
getTriple().isOSBinFormatMachO())
3196 Section = (ObjCABI == 2) ?
"__DATA, __objc_const"
3197 :
"__OBJC,__property,regular,no_dead_strip";
3199 llvm::GlobalVariable *GV =
3200 CreateMetadataVar(Name, values, Section, CGM.
getPointerAlign(),
true);
3204llvm::Constant *CGObjCCommonMac::EmitProtocolMethodTypes(
3206 const ObjCCommonTypesHelper &ObjCTypes) {
3208 if (MethodTypes.empty())
3209 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
3211 llvm::ArrayType *AT =
3212 llvm::ArrayType::get(ObjCTypes.Int8PtrTy, MethodTypes.size());
3213 llvm::Constant *
Init = llvm::ConstantArray::get(AT, MethodTypes);
3216 if (CGM.
getTriple().isOSBinFormatMachO() && ObjCABI == 2)
3217 Section =
"__DATA, __objc_const";
3219 llvm::GlobalVariable *GV =
3248 llvm::raw_svector_ostream(ExtName)
3252 auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
3254 enum { InstanceMethods, ClassMethods, NumMethodLists };
3256 for (
const auto *MD : OCD->
methods()) {
3257 if (!MD->isDirectMethod())
3258 Methods[
unsigned(MD->isClassMethod())].push_back(MD);
3261 Values.add(GetClassName(OCD->
getName()));
3262 Values.add(GetClassName(
Interface->getObjCRuntimeNameAsString()));
3263 LazySymbols.insert(
Interface->getIdentifier());
3265 Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
3266 Methods[InstanceMethods]));
3267 Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
3268 Methods[ClassMethods]));
3270 Values.add(EmitProtocolList(
"OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
3274 Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
3276 Values.addInt(ObjCTypes.IntTy, Size);
3280 Values.add(EmitPropertyList(
"_OBJC_$_PROP_LIST_" + ExtName.str(), OCD,
3282 Values.add(EmitPropertyList(
"_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), OCD,
3285 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3286 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3289 llvm::GlobalVariable *GV = CreateMetadataVar(
3290 "OBJC_CATEGORY_" + ExtName.str(), Values,
3291 "__OBJC,__category,regular,no_dead_strip", CGM.
getPointerAlign(),
true);
3292 DefinedCategories.push_back(GV);
3293 DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
3295 MethodDefinitions.clear();
3356 if (
auto *RD =
type->getAsRecordDecl()) {
3357 for (
auto *field : RD->
fields()) {
3373 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
3376 ID->getClassInterface()->all_declared_ivar_begin();
3377 ivar; ivar = ivar->getNextIvar()) {
3407 DefinedSymbols.insert(RuntimeName);
3409 std::string ClassName =
ID->getNameAsString();
3413 llvm::Constant *Protocols =
3414 EmitProtocolList(
"OBJC_CLASS_PROTOCOLS_" +
ID->getName(),
3415 Interface->all_referenced_protocol_begin(),
3416 Interface->all_referenced_protocol_end());
3418 if (
ID->hasNonZeroConstructors() ||
ID->hasDestructors())
3421 bool hasMRCWeak =
false;
3436 enum { InstanceMethods, ClassMethods, NumMethodLists };
3438 for (
const auto *MD :
ID->methods()) {
3439 if (!MD->isDirectMethod())
3440 Methods[
unsigned(MD->isClassMethod())].push_back(MD);
3443 for (
const auto *PID :
ID->property_impls()) {
3445 if (PID->getPropertyDecl()->isDirectProperty())
3448 if (GetMethodDefinition(MD))
3449 Methods[InstanceMethods].push_back(MD);
3451 if (GetMethodDefinition(MD))
3452 Methods[InstanceMethods].push_back(MD);
3457 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3458 values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
3461 LazySymbols.insert(Super->getIdentifier());
3463 values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
3465 values.addNullPointer(ObjCTypes.ClassPtrTy);
3467 values.add(GetClassName(
ID->getObjCRuntimeNameAsString()));
3469 values.addInt(ObjCTypes.LongTy, 0);
3470 values.addInt(ObjCTypes.LongTy, Flags);
3471 values.addInt(ObjCTypes.LongTy,
Size.getQuantity());
3472 values.add(EmitIvarList(ID,
false));
3473 values.add(emitMethodList(
ID->getName(), MethodListType::InstanceMethods,
3474 Methods[InstanceMethods]));
3476 values.addNullPointer(ObjCTypes.CachePtrTy);
3477 values.add(Protocols);
3479 values.add(EmitClassExtension(ID, Size, hasMRCWeak,
3482 std::string Name(
"OBJC_CLASS_");
3484 const char *Section =
"__OBJC,__class,regular,no_dead_strip";
3486 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3488 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3489 "Forward metaclass reference has incorrect type.");
3490 values.finishAndSetAsInitializer(GV);
3491 GV->setSection(Section);
3495 GV = CreateMetadataVar(Name, values, Section, CGM.
getPointerAlign(),
true);
3496 DefinedClasses.push_back(GV);
3497 ImplementedClasses.push_back(
Interface);
3499 MethodDefinitions.clear();
3504 llvm::Constant *Protocols,
3513 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3523 values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
3525 values.addNullPointer(ObjCTypes.ClassPtrTy);
3527 values.add(GetClassName(
ID->getObjCRuntimeNameAsString()));
3529 values.addInt(ObjCTypes.LongTy, 0);
3530 values.addInt(ObjCTypes.LongTy, Flags);
3531 values.addInt(ObjCTypes.LongTy, Size);
3532 values.add(EmitIvarList(ID,
true));
3534 emitMethodList(
ID->getName(), MethodListType::ClassMethods, Methods));
3536 values.addNullPointer(ObjCTypes.CachePtrTy);
3537 values.add(Protocols);
3539 values.addNullPointer(ObjCTypes.Int8PtrTy);
3544 std::string Name(
"OBJC_METACLASS_");
3545 Name +=
ID->getName();
3548 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3550 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3551 "Forward metaclass reference has incorrect type.");
3552 values.finishAndSetAsInitializer(GV);
3556 llvm::GlobalValue::PrivateLinkage);
3558 GV->setSection(
"__OBJC,__meta_class,regular,no_dead_strip");
3565 std::string Name =
"OBJC_METACLASS_" +
ID->getNameAsString();
3575 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3577 GV =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ClassTy,
false,
3578 llvm::GlobalValue::PrivateLinkage,
nullptr,
3581 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3582 "Forward metaclass reference has incorrect type.");
3587 std::string Name =
"OBJC_CLASS_" +
ID->getNameAsString();
3588 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3591 GV =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ClassTy,
false,
3592 llvm::GlobalValue::PrivateLinkage,
nullptr,
3595 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3596 "Forward class metadata reference has incorrect type.");
3616 llvm::Constant *layout;
3618 layout = llvm::ConstantPointerNull::get(CGM.
Int8PtrTy);
3625 llvm::Constant *propertyList =
3626 EmitPropertyList((isMetaclass ? Twine(
"_OBJC_$_CLASS_PROP_LIST_")
3627 : Twine(
"_OBJC_$_PROP_LIST_")) +
3629 ID,
ID->getClassInterface(), ObjCTypes, isMetaclass);
3632 if (layout->isNullValue() && propertyList->isNullValue()) {
3633 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
3637 CGM.
getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
3640 auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
3641 values.addInt(ObjCTypes.IntTy, size);
3643 values.add(propertyList);
3645 return CreateMetadataVar(
"OBJC_CLASSEXT_" +
ID->getName(), values,
3646 "__OBJC,__class_ext,regular,no_dead_strip",
3670 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
3675 auto ivarList = builder.beginStruct();
3676 auto countSlot = ivarList.addPlaceholder();
3677 auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
3682 if (!IVD->getDeclName())
3685 auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
3686 ivar.add(GetMethodVarName(IVD->getIdentifier()));
3687 ivar.add(GetMethodVarType(IVD));
3688 ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
3689 ivar.finishAndAddTo(ivars);
3693 auto count = ivars.size();
3697 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
3700 ivars.finishAndAddTo(ivarList);
3701 ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
3703 llvm::GlobalVariable *GV;
3704 GV = CreateMetadataVar(
"OBJC_INSTANCE_VARIABLES_" +
ID->getName(), ivarList,
3705 "__OBJC,__instance_vars,regular,no_dead_strip",
3718 auto description = builder.
beginStruct(ObjCTypes.MethodDescriptionTy);
3719 description.add(GetMethodVarName(MD->
getSelector()));
3720 description.add(GetMethodVarType(MD));
3721 description.finishAndAddTo(builder);
3733 llvm::Function *fn = GetMethodDefinition(MD);
3734 assert(fn &&
"no definition registered for method");
3736 auto method = builder.
beginStruct(ObjCTypes.MethodTy);
3738 method.add(GetMethodVarType(MD));
3740 method.finishAndAddTo(builder);
3757CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
3761 bool forProtocol =
false;
3763 case MethodListType::CategoryInstanceMethods:
3764 prefix =
"OBJC_CATEGORY_INSTANCE_METHODS_";
3765 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3766 forProtocol =
false;
3768 case MethodListType::CategoryClassMethods:
3769 prefix =
"OBJC_CATEGORY_CLASS_METHODS_";
3770 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3771 forProtocol =
false;
3773 case MethodListType::InstanceMethods:
3774 prefix =
"OBJC_INSTANCE_METHODS_";
3775 section =
"__OBJC,__inst_meth,regular,no_dead_strip";
3776 forProtocol =
false;
3778 case MethodListType::ClassMethods:
3779 prefix =
"OBJC_CLASS_METHODS_";
3780 section =
"__OBJC,__cls_meth,regular,no_dead_strip";
3781 forProtocol =
false;
3783 case MethodListType::ProtocolInstanceMethods:
3784 prefix =
"OBJC_PROTOCOL_INSTANCE_METHODS_";
3785 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3788 case MethodListType::ProtocolClassMethods:
3789 prefix =
"OBJC_PROTOCOL_CLASS_METHODS_";
3790 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3793 case MethodListType::OptionalProtocolInstanceMethods:
3794 prefix =
"OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
3795 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3798 case MethodListType::OptionalProtocolClassMethods:
3799 prefix =
"OBJC_PROTOCOL_CLASS_METHODS_OPT_";
3800 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3806 if (methods.empty())
3807 return llvm::Constant::getNullValue(
3808 forProtocol ? ObjCTypes.MethodDescriptionListPtrTy
3809 : ObjCTypes.MethodListPtrTy);
3816 values.addInt(ObjCTypes.IntTy, methods.size());
3817 auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
3818 for (
auto MD : methods) {
3819 emitMethodDescriptionConstant(methodArray, MD);
3821 methodArray.finishAndAddTo(values);
3823 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3831 values.addNullPointer(ObjCTypes.Int8PtrTy);
3832 values.addInt(ObjCTypes.IntTy, methods.size());
3833 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
3834 for (
auto MD : methods) {
3836 emitMethodConstant(methodArray, MD);
3838 methodArray.finishAndAddTo(values);
3840 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3845llvm::Function *CGObjCCommonMac::GenerateMethod(
const ObjCMethodDecl *OMD,
3850 Method = GenerateDirectMethod(OMD, CD);
3852 auto Name = getSymbolNameForMethod(OMD);
3855 llvm::FunctionType *MethodTy =
3856 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
3857 Method = llvm::Function::Create(
3858 MethodTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3861 MethodDefinitions.insert(std::make_pair(OMD, Method));
3870 auto I = DirectMethodDefinitions.find(COMD);
3871 llvm::Function *OldFn =
nullptr, *
Fn =
nullptr;
3873 if (I != DirectMethodDefinitions.end()) {
3889 llvm::FunctionType *MethodTy =
3890 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
3893 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
3895 Fn->takeName(OldFn);
3896 OldFn->replaceAllUsesWith(Fn);
3897 OldFn->eraseFromParent();
3902 auto Name = getSymbolNameForMethod(OMD,
false);
3904 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
3906 DirectMethodDefinitions.insert(std::make_pair(COMD, Fn));
3912void CGObjCCommonMac::GenerateDirectMethodPrologue(
3916 bool ReceiverCanBeNull =
true;
3918 auto selfValue = Builder.CreateLoad(selfAddr);
3936 "GenerateDirectMethod() should be called with the Class Interface");
3949 result = GeneratePossiblySpecializedMessageSend(
3957 ReceiverCanBeNull = isWeakLinkedClass(OID);
3960 if (ReceiverCanBeNull) {
3961 llvm::BasicBlock *SelfIsNilBlock =
3963 llvm::BasicBlock *ContBlock =
3967 auto selfTy = cast<llvm::PointerType>(selfValue->getType());
3968 auto Zero = llvm::ConstantPointerNull::get(selfTy);
3971 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue,
Zero), SelfIsNilBlock,
3972 ContBlock, MDHelper.createUnlikelyBranchWeights());
3978 Builder.SetInsertPoint(SelfIsNilBlock);
3979 if (!retTy->isVoidType()) {
3987 Builder.SetInsertPoint(ContBlock);
3995 Builder.CreateStore(GetSelector(CGF, OMD),
4000llvm::GlobalVariable *
4004 llvm::GlobalValue::LinkageTypes
LT =
4006 llvm::GlobalVariable *GV =
4007 Init.finishAndCreateGlobal(Name, Align,
false,
LT);
4008 if (!Section.empty())
4009 GV->setSection(Section);
4015llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
4016 llvm::Constant *
Init,
4020 llvm::Type *Ty =
Init->getType();
4021 llvm::GlobalValue::LinkageTypes
LT =
4023 llvm::GlobalVariable *GV =
4025 if (!Section.empty())
4026 GV->setSection(Section);
4033llvm::GlobalVariable *
4034CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType
Type,
4035 bool ForceNonFragileABI,
4036 bool NullTerminate) {
4039 case ObjCLabelType::ClassName:
4040 Label =
"OBJC_CLASS_NAME_";
4042 case ObjCLabelType::MethodVarName:
4043 Label =
"OBJC_METH_VAR_NAME_";
4045 case ObjCLabelType::MethodVarType:
4046 Label =
"OBJC_METH_VAR_TYPE_";
4048 case ObjCLabelType::PropertyName:
4049 Label =
"OBJC_PROP_NAME_ATTR_";
4053 bool NonFragile = ForceNonFragileABI || isNonFragileABI();
4057 case ObjCLabelType::ClassName:
4058 Section = NonFragile ?
"__TEXT,__objc_classname,cstring_literals"
4059 :
"__TEXT,__cstring,cstring_literals";
4061 case ObjCLabelType::MethodVarName:
4062 Section = NonFragile ?
"__TEXT,__objc_methname,cstring_literals"
4063 :
"__TEXT,__cstring,cstring_literals";
4065 case ObjCLabelType::MethodVarType:
4066 Section = NonFragile ?
"__TEXT,__objc_methtype,cstring_literals"
4067 :
"__TEXT,__cstring,cstring_literals";
4069 case ObjCLabelType::PropertyName:
4070 Section = NonFragile ?
"__TEXT,__objc_methname,cstring_literals"
4071 :
"__TEXT,__cstring,cstring_literals";
4075 llvm::Constant *
Value =
4076 llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
4077 llvm::GlobalVariable *GV =
new llvm::GlobalVariable(
4079 true, llvm::GlobalValue::PrivateLinkage,
Value,
Label);
4080 if (CGM.
getTriple().isOSBinFormatMachO())
4081 GV->setSection(Section);
4082 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4089llvm::Function *CGObjCMac::ModuleInitFunction() {
4095llvm::FunctionCallee CGObjCMac::GetPropertyGetFunction() {
4096 return ObjCTypes.getGetPropertyFn();
4099llvm::FunctionCallee CGObjCMac::GetPropertySetFunction() {
4100 return ObjCTypes.getSetPropertyFn();
4103llvm::FunctionCallee CGObjCMac::GetOptimizedPropertySetFunction(
bool atomic,
4105 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
4108llvm::FunctionCallee CGObjCMac::GetGetStructFunction() {
4109 return ObjCTypes.getCopyStructFn();
4112llvm::FunctionCallee CGObjCMac::GetSetStructFunction() {
4113 return ObjCTypes.getCopyStructFn();
4116llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectGetFunction() {
4117 return ObjCTypes.getCppAtomicObjectFunction();
4120llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectSetFunction() {
4121 return ObjCTypes.getCppAtomicObjectFunction();
4124llvm::FunctionCallee CGObjCMac::EnumerationMutationFunction() {
4125 return ObjCTypes.getEnumerationMutationFn();
4129 return EmitTryOrSynchronizedStmt(CGF, S);
4134 return EmitTryOrSynchronizedStmt(CGF, S);
4143 ObjCTypesHelper &ObjCTypes;
4144 PerformFragileFinally(
const Stmt *S,
Address SyncArgSlot,
4146 ObjCTypesHelper *ObjCTypes)
4147 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
4148 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
4153 llvm::BasicBlock *FinallyCallExit =
4155 llvm::BasicBlock *FinallyNoCallExit =
4158 FinallyCallExit, FinallyNoCallExit);
4166 if (isa<ObjCAtTryStmt>(S)) {
4168 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
4170 if (flags.isForEHCleanup())
4175 llvm::Value *CurCleanupDest =
4178 CGF.
EmitStmt(FinallyStmt->getFinallyBody());
4197class FragileHazards {
4200 llvm::DenseSet<llvm::BasicBlock *> BlocksBeforeTry;
4202 llvm::InlineAsm *ReadHazard;
4203 llvm::InlineAsm *WriteHazard;
4205 llvm::FunctionType *GetAsmFnType();
4207 void collectLocals();
4213 void emitWriteHazard();
4214 void emitHazardsInNewBlocks();
4230 for (llvm::BasicBlock &BB : *CGF.
CurFn)
4231 BlocksBeforeTry.insert(&BB);
4233 llvm::FunctionType *AsmFnTy = GetAsmFnType();
4241 std::string Constraint;
4242 for (
unsigned I = 0,
E = Locals.size(); I !=
E; ++I) {
4248 ReadHazard = llvm::InlineAsm::get(AsmFnTy,
"", Constraint,
true,
false);
4256 std::string Constraint;
4257 for (
unsigned I = 0,
E = Locals.size(); I !=
E; ++I) {
4260 Constraint +=
"=*m";
4263 WriteHazard = llvm::InlineAsm::get(AsmFnTy,
"", Constraint,
true,
false);
4268void FragileHazards::emitWriteHazard() {
4273 for (
auto Pair : llvm::enumerate(Locals))
4276 llvm::Attribute::get(
4278 cast<llvm::AllocaInst>(Pair.value())->getAllocatedType()));
4281void FragileHazards::emitReadHazard(
CGBuilderTy &Builder) {
4282 assert(!Locals.empty());
4283 llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
4284 call->setDoesNotThrow();
4286 for (
auto Pair : llvm::enumerate(Locals))
4289 llvm::Attribute::get(
4290 Builder.getContext(), llvm::Attribute::ElementType,
4291 cast<llvm::AllocaInst>(Pair.value())->getAllocatedType()));
4296void FragileHazards::emitHazardsInNewBlocks() {
4303 for (llvm::BasicBlock &BB : *CGF.
CurFn) {
4304 if (BlocksBeforeTry.count(&BB))
4308 for (llvm::BasicBlock::iterator BI = BB.begin(), BE = BB.end(); BI != BE;
4310 llvm::Instruction &I = *BI;
4314 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I))
4316 if (isa<llvm::IntrinsicInst>(I))
4321 if (cast<llvm::CallBase>(I).doesNotThrow())
4329 Builder.SetInsertPoint(&BB, BI);
4330 emitReadHazard(Builder);
4337 if (llvm::Value *Ptr =
V.getBasePointer())
4341void FragileHazards::collectLocals() {
4343 llvm::DenseSet<llvm::Value *> AllocasToIgnore;
4349 llvm::BasicBlock &Entry = CGF.
CurFn->getEntryBlock();
4350 for (llvm::Instruction &I : Entry)
4351 if (isa<llvm::AllocaInst>(I) && !AllocasToIgnore.count(&I))
4352 Locals.push_back(&I);
4355llvm::FunctionType *FragileHazards::GetAsmFnType() {
4357 for (
unsigned i = 0, e = Locals.size(); i != e; ++i)
4358 tys[i] = Locals[i]->getType();
4359 return llvm::FunctionType::get(CGF.
VoidTy, tys,
false);
4472 bool isTry = isa<ObjCAtTryStmt>(S);
4491 llvm::Value *SyncArg =
4492 CGF.
EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
4493 SyncArg = CGF.
Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
4504 ObjCTypes.ExceptionDataTy, CGF.
getPointerAlign(),
"exceptiondata.ptr");
4510 FragileHazards Hazards(CGF);
4529 SyncArgSlot, CallTryExitVar,
4530 ExceptionData, &ObjCTypes);
4536 ExceptionData.emitRawPointer(CGF));
4539 llvm::Constant *
Zero = llvm::ConstantInt::get(CGF.
Builder.getInt32Ty(), 0);
4542 ObjCTypes.ExceptionDataTy, ExceptionData.emitRawPointer(CGF), GEPIndexes,
4545 ObjCTypes.getSetJmpFn(), SetJmpBuffer,
"setjmp_result");
4546 SetJmpResult->setCanReturnTwice();
4552 llvm::Value *DidCatch =
4553 CGF.
Builder.CreateIsNotNull(SetJmpResult,
"did_catch_exception");
4554 CGF.
Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
4559 CGF.
EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
4560 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
4562 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.
Builder.saveAndClearIP();
4568 Hazards.emitWriteHazard();
4572 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
4582 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF),
4593 llvm::BasicBlock *CatchBlock =
nullptr;
4594 llvm::BasicBlock *CatchHandler =
nullptr;
4605 ExceptionData.emitRawPointer(CGF));
4608 ObjCTypes.getSetJmpFn(), SetJmpBuffer,
"setjmp.result");
4609 SetJmpResult->setCanReturnTwice();
4611 llvm::Value *Threw =
4612 CGF.
Builder.CreateIsNotNull(SetJmpResult,
"did_catch_exception");
4616 CGF.
Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
4626 bool AllMatched =
false;
4628 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
4654 EmitInitOfCatchParam(CGF, Caught, CatchParam);
4657 CGF.
EmitStmt(CatchStmt->getCatchBody());
4660 CatchVarCleanups.ForceCleanup();
4666 assert(OPT &&
"Unexpected non-object pointer type in @catch");
4671 assert(IDecl &&
"Catch parameter must have Objective-C type!");
4674 llvm::Value *
Class = EmitClassRef(CGF, IDecl);
4676 llvm::Value *matchArgs[] = {
Class, Caught};
4678 ObjCTypes.getExceptionMatchFn(), matchArgs,
"match");
4684 MatchedBlock, NextCatchBlock);
4697 llvm::Value *Tmp = CGF.
Builder.CreateBitCast(
4699 EmitInitOfCatchParam(CGF, Tmp, CatchParam);
4701 CGF.
EmitStmt(CatchStmt->getCatchBody());
4704 CatchVarCleanups.ForceCleanup();
4715 if (Caught->use_empty())
4716 Caught->eraseFromParent();
4732 assert(PropagatingExnVar.
isValid());
4734 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF),
4745 Hazards.emitHazardsInNewBlocks();
4748 CGF.
Builder.restoreIP(TryFallthroughIP);
4755 CGBuilderTy::InsertPoint SavedIP = CGF.
Builder.saveAndClearIP();
4759 llvm::Value *PropagatingExn;
4760 if (PropagatingExnVar.
isValid()) {
4766 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF));
4767 PropagatingExn = Caught;
4772 CGF.
Builder.CreateUnreachable();
4775 CGF.
Builder.restoreIP(SavedIP);
4780 bool ClearInsertionPoint) {
4781 llvm::Value *ExceptionAsObject;
4783 if (
const Expr *ThrowExpr = S.getThrowExpr()) {
4786 CGF.
Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
4789 "Unexpected rethrow outside @catch block.");
4793 CGF.
EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
4794 ->setDoesNotReturn();
4795 CGF.
Builder.CreateUnreachable();
4798 if (ClearInsertionPoint)
4799 CGF.
Builder.ClearInsertionPoint();
4808 llvm::Value *AddrWeakObjVal = CGF.
Builder.CreateBitCast(
4811 ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal,
"weakread");
4812 read_weak = CGF.
Builder.CreateBitCast(read_weak, DestTy);
4820 llvm::Value *src,
Address dst) {
4821 llvm::Type *SrcTy = src->getType();
4822 if (!isa<llvm::PointerType>(SrcTy)) {
4824 assert(Size <= 8 && "does not support size > 8
");
4825 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4826 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4827 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4829 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4830 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4831 ObjCTypes.PtrObjectPtrTy);
4832 llvm::Value *args[] = {src, dstVal};
4833 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args,
4840void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
4841 llvm::Value *src, Address dst,
4843 llvm::Type *SrcTy = src->getType();
4844 if (!isa<llvm::PointerType>(SrcTy)) {
4845 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4846 assert(Size <= 8 && "does
not support size > 8
");
4847 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4848 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4849 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4851 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4852 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4853 ObjCTypes.PtrObjectPtrTy);
4854 llvm::Value *args[] = {src, dstVal};
4856 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), args,
4859 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), args,
4860 "threadlocalassign
");
4866void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
4867 llvm::Value *src, Address dst,
4868 llvm::Value *ivarOffset) {
4869 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is
NULL");
4870 llvm::Type *SrcTy = src->getType();
4871 if (!isa<llvm::PointerType>(SrcTy)) {
4872 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4873 assert(Size <= 8 && "does
not support size > 8
");
4874 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4875 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4876 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4878 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4879 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4880 ObjCTypes.PtrObjectPtrTy);
4881 llvm::Value *args[] = {src, dstVal, ivarOffset};
4882 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
4888void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
4889 llvm::Value *src, Address dst) {
4890 llvm::Type *SrcTy = src->getType();
4891 if (!isa<llvm::PointerType>(SrcTy)) {
4892 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4893 assert(Size <= 8 && "does
not support size > 8
");
4894 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4895 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4896 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4898 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4899 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4900 ObjCTypes.PtrObjectPtrTy);
4901 llvm::Value *args[] = {src, dstVal};
4902 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args,
4906void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
4907 Address DestPtr, Address SrcPtr,
4908 llvm::Value *size) {
4909 llvm::Value *args[] = {DestPtr.emitRawPointer(CGF),
4910 SrcPtr.emitRawPointer(CGF), size};
4911 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
4916LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
4918 llvm::Value *BaseValue,
4919 const ObjCIvarDecl *Ivar,
4920 unsigned CVRQualifiers) {
4921 const ObjCInterfaceDecl *ID =
4922 ObjectTy->castAs<ObjCObjectType>()->getInterface();
4923 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4924 EmitIvarOffset(CGF, ID, Ivar));
4927llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
4928 const ObjCInterfaceDecl *Interface,
4929 const ObjCIvarDecl *Ivar) {
4930 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
4931 return llvm::ConstantInt::get(
4932 CGM.getTypes().ConvertType(CGM.getContext().LongTy), Offset);
4935/* *** Private Interface *** */
4937std::string CGObjCCommonMac::GetSectionName(StringRef Section,
4938 StringRef MachOAttributes) {
4939 switch (CGM.getTriple().getObjectFormat()) {
4940 case llvm::Triple::UnknownObjectFormat:
4941 llvm_unreachable("unexpected
object file format
");
4942 case llvm::Triple::MachO: {
4943 if (MachOAttributes.empty())
4944 return ("__DATA,
" + Section).str();
4945 return ("__DATA,
" + Section + ",
" + MachOAttributes).str();
4947 case llvm::Triple::ELF:
4948 assert(Section.starts_with("__
") && "expected the name to begin with __
");
4949 return Section.substr(2).str();
4950 case llvm::Triple::COFF:
4951 assert(Section.starts_with("__
") && "expected the name to begin with __
");
4952 return (".
" + Section.substr(2) + "$B
").str();
4953 case llvm::Triple::Wasm:
4954 case llvm::Triple::GOFF:
4955 case llvm::Triple::SPIRV:
4956 case llvm::Triple::XCOFF:
4957 case llvm::Triple::DXContainer:
4958 llvm::report_fatal_error(
4959 "Objective-
C support is unimplemented
for object file format
");
4962 llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType
enum");
4974enum ImageInfoFlags {
4975 eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
4976 eImageInfo_GarbageCollected = (1 << 1),
4977 eImageInfo_GCOnly = (1 << 2),
4978 eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
4980 eImageInfo_SignedClassRO = (1 << 4), // Reused (was _CorrectedSynthesize)
4981 eImageInfo_ImageIsSimulated = (1 << 5),
4982 eImageInfo_ClassProperties = (1 << 6)
4986void CGObjCCommonMac::EmitImageInfo() {
4987 unsigned version = 0; // Version is unused?
4988 std::string Section =
4990 ? "__OBJC,__image_info,regular
"
4991 : GetSectionName("__objc_imageinfo
", "regular,no_dead_strip
");
4993 // Generate module-level named metadata to convey this information to the
4994 // linker and code-gen.
4995 llvm::Module &Mod = CGM.getModule();
4997 // Add the ObjC ABI version to the module flags.
4998 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Version
", ObjCABI);
4999 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Image Info Version
",
5001 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Image Info Section
",
5002 llvm::MDString::get(VMContext, Section));
5004 auto Int8Ty = llvm::Type::getInt8Ty(VMContext);
5005 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
5006 // Non-GC overrides those files which specify GC.
5007 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Garbage Collection
",
5008 llvm::ConstantInt::get(Int8Ty, 0));
5010 // Add the ObjC garbage collection value.
5012 llvm::Module::Error, "Objective-
C Garbage Collection
",
5013 llvm::ConstantInt::get(Int8Ty, (uint8_t)eImageInfo_GarbageCollected));
5015 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
5016 // Add the ObjC GC Only value.
5017 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C GC Only
",
5020 // Require that GC be specified and set to eImageInfo_GarbageCollected.
5021 llvm::Metadata *Ops[2] = {
5022 llvm::MDString::get(VMContext, "Objective-
C Garbage Collection
"),
5023 llvm::ConstantAsMetadata::get(
5024 llvm::ConstantInt::get(Int8Ty, eImageInfo_GarbageCollected))};
5025 Mod.addModuleFlag(llvm::Module::Require, "Objective-
C GC Only
",
5026 llvm::MDNode::get(VMContext, Ops));
5030 // Indicate whether we're compiling this to run on a simulator.
5031 if (CGM.getTarget().getTriple().isSimulatorEnvironment())
5032 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Is Simulated
",
5033 eImageInfo_ImageIsSimulated);
5035 // Indicate whether we are generating class properties.
5036 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Class Properties
",
5037 eImageInfo_ClassProperties);
5039 // Indicate whether we want enforcement of pointer signing for class_ro_t
5041 if (CGM.getLangOpts().PointerAuthObjcClassROPointers)
5042 Mod.addModuleFlag(llvm::Module::Error,
5043 "Objective-
C Enforce ClassRO
Pointer Signing
",
5044 eImageInfo_SignedClassRO);
5046 Mod.addModuleFlag(llvm::Module::Error,
5047 "Objective-
C Enforce ClassRO
Pointer Signing
",
5048 llvm::ConstantInt::get(Int8Ty, 0));
5051// struct objc_module {
5052// unsigned long version;
5053// unsigned long size;
5058// FIXME: Get from somewhere
5059static const int ModuleVersion = 7;
5061void CGObjCMac::EmitModuleInfo() {
5062 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
5064 ConstantInitBuilder builder(CGM);
5065 auto values = builder.beginStruct(ObjCTypes.ModuleTy);
5066 values.addInt(ObjCTypes.LongTy, ModuleVersion);
5067 values.addInt(ObjCTypes.LongTy, Size);
5068 // This used to be the filename, now it is unused. <rdr://4327263>
5069 values.add(GetClassName(StringRef("")));
5070 values.add(EmitModuleSymbols());
5071 CreateMetadataVar("OBJC_MODULES
", values,
5072 "__OBJC,__module_info,regular,no_dead_strip
",
5073 CGM.getPointerAlign(), true);
5076llvm::Constant *CGObjCMac::EmitModuleSymbols() {
5077 unsigned NumClasses = DefinedClasses.size();
5078 unsigned NumCategories = DefinedCategories.size();
5080 // Return null if no symbols were defined.
5081 if (!NumClasses && !NumCategories)
5082 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
5084 ConstantInitBuilder builder(CGM);
5085 auto values = builder.beginStruct();
5086 values.addInt(ObjCTypes.LongTy, 0);
5087 values.addNullPointer(ObjCTypes.SelectorPtrTy);
5088 values.addInt(ObjCTypes.ShortTy, NumClasses);
5089 values.addInt(ObjCTypes.ShortTy, NumCategories);
5091 // The runtime expects exactly the list of defined classes followed
5092 // by the list of defined categories, in a single array.
5093 auto array = values.beginArray(ObjCTypes.Int8PtrTy);
5094 for (unsigned i = 0; i < NumClasses; i++) {
5095 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
5097 if (ObjCImplementationDecl *IMP = ID->getImplementation())
5098 // We are implementing a weak imported interface. Give it external linkage
5099 if (ID->isWeakImported() && !IMP->isWeakImported())
5100 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
5102 array.add(DefinedClasses[i]);
5104 for (unsigned i = 0; i < NumCategories; i++)
5105 array.add(DefinedCategories[i]);
5107 array.finishAndAddTo(values);
5109 llvm::GlobalVariable *GV = CreateMetadataVar(
5110 "OBJC_SYMBOLS
", values, "__OBJC,__symbols,regular,no_dead_strip
",
5111 CGM.getPointerAlign(), true);
5115llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
5116 IdentifierInfo *II) {
5117 LazySymbols.insert(II);
5119 llvm::GlobalVariable *&Entry = ClassReferences[II];
5123 CreateMetadataVar("OBJC_CLASS_REFERENCES_
", GetClassName(II->getName()),
5124 "__OBJC,__cls_refs,literal_pointers,no_dead_strip
",
5125 CGM.getPointerAlign(), true);
5128 return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry,
5129 CGF.getPointerAlign());
5132llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
5133 const ObjCInterfaceDecl *ID) {
5134 // If the class has the objc_runtime_visible attribute, we need to
5135 // use the Objective-C runtime to get the class.
5136 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
5137 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
5139 IdentifierInfo *RuntimeName =
5140 &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
5141 return EmitClassRefFromId(CGF, RuntimeName);
5144llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
5145 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool
");
5146 return EmitClassRefFromId(CGF, II);
5149llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
5150 return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel));
5153ConstantAddress CGObjCMac::EmitSelectorAddr(Selector Sel) {
5154 CharUnits Align = CGM.getPointerAlign();
5156 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
5158 Entry = CreateMetadataVar(
5159 "OBJC_SELECTOR_REFERENCES_
", GetMethodVarName(Sel),
5160 "__OBJC,__message_refs,literal_pointers,no_dead_strip
", Align, true);
5161 Entry->setExternallyInitialized(true);
5164 return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align);
5167llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
5168 llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
5170 Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
5171 return getConstantGEP(VMContext, Entry, 0, 0);
5174llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
5175 return MethodDefinitions.lookup(MD);
5181CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
5182 const ObjCCommonTypesHelper &ObjCTypes) {
5183 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
5186void IvarLayoutBuilder::visitRecord(const RecordType *RT, CharUnits offset) {
5187 const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
5189 // If this is a union, remember that we had one, because it might mess
5190 // up the ordering of layout entries.
5192 IsDisordered = true;
5194 const ASTRecordLayout *recLayout = nullptr;
5195 visitAggregate(RD->field_begin(), RD->field_end(), offset,
5196 [&](const FieldDecl *field) -> CharUnits {
5198 recLayout = &CGM.getContext().getASTRecordLayout(RD);
5200 recLayout->getFieldOffset(field->getFieldIndex());
5201 return CGM.getContext().toCharUnitsFromBits(offsetInBits);
5205template <class Iterator, class GetOffsetFn>
5206void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
5207 CharUnits aggregateOffset,
5208 const GetOffsetFn &getOffset) {
5209 for (; begin != end; ++begin) {
5210 auto field = *begin;
5212 // Skip over bitfields.
5213 if (field->isBitField()) {
5217 // Compute the offset of the field within the aggregate.
5218 CharUnits fieldOffset = aggregateOffset + getOffset(field);
5220 visitField(field, fieldOffset);
5225void IvarLayoutBuilder::visitField(const FieldDecl *field,
5226 CharUnits fieldOffset) {
5227 QualType fieldType = field->getType();
5229 // Drill down into arrays.
5230 uint64_t numElts = 1;
5231 if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) {
5233 fieldType = arrayType->getElementType();
5235 // Unlike incomplete arrays, constant arrays can be nested.
5236 while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
5237 numElts *= arrayType->getZExtSize();
5238 fieldType = arrayType->getElementType();
5241 assert(!fieldType->isArrayType() && "ivar of non-constant array
type?
");
5243 // If we ended up with a zero-sized array, we've done what we can do within
5244 // the limits of this layout encoding.
5248 // Recurse if the base element type is a record type.
5249 if (const auto *recType = fieldType->getAsCanonical<RecordType>()) {
5250 size_t oldEnd = IvarsInfo.size();
5252 visitRecord(recType, fieldOffset);
5254 // If we have an array, replicate the first entry's layout information.
5255 auto numEltEntries = IvarsInfo.size() - oldEnd;
5256 if (numElts != 1 && numEltEntries != 0) {
5257 CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
5258 for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
5259 // Copy the last numEltEntries onto the end of the array, adjusting
5260 // each for the element size.
5261 for (size_t i = 0; i != numEltEntries; ++i) {
5262 auto firstEntry = IvarsInfo[oldEnd + i];
5263 IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
5264 firstEntry.SizeInWords));
5272 // Classify the element type.
5273 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
5275 // If it matches what we're looking for, add an entry.
5276 if ((ForStrongLayout && GCAttr == Qualifiers::Strong) ||
5277 (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
5278 assert(CGM.getContext().getTypeSizeInChars(fieldType) ==
5279 CGM.getPointerSize());
5280 IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
5288IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
5289 llvm::SmallVectorImpl<unsigned char> &buffer) {
5290 // The bitmap is a series of skip/scan instructions, aligned to word
5291 // boundaries. The skip is performed first.
5292 const unsigned char MaxNibble = 0xF;
5293 const unsigned char SkipMask = 0xF0, SkipShift = 4;
5294 const unsigned char ScanMask = 0x0F, ScanShift = 0;
5296 assert(!IvarsInfo.empty() && "generating bitmap
for no data
");
5298 // Sort the ivar info on byte position in case we encounterred a
5299 // union nested in the ivar list.
5301 // This isn't a stable sort, but our algorithm should handle it fine.
5302 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
5304 assert(llvm::is_sorted(IvarsInfo));
5306 assert(IvarsInfo.back().Offset < InstanceEnd);
5308 assert(buffer.empty());
5310 // Skip the next N words.
5311 auto skip = [&](unsigned numWords) {
5312 assert(numWords > 0);
5314 // Try to merge into the previous byte. Since scans happen second, we
5315 // can't do this if it includes a scan.
5316 if (!buffer.empty() && !(buffer.back() & ScanMask)) {
5317 unsigned lastSkip = buffer.back() >> SkipShift;
5318 if (lastSkip < MaxNibble) {
5319 unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
5320 numWords -= claimed;
5321 lastSkip += claimed;
5322 buffer.back() = (lastSkip << SkipShift);
5326 while (numWords >= MaxNibble) {
5327 buffer.push_back(MaxNibble << SkipShift);
5328 numWords -= MaxNibble;
5331 buffer.push_back(numWords << SkipShift);
5335 // Scan the next N words.
5336 auto scan = [&](unsigned numWords) {
5337 assert(numWords > 0);
5339 // Try to merge into the previous byte. Since scans happen second, we can
5340 // do this even if it includes a skip.
5341 if (!buffer.empty()) {
5342 unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
5343 if (lastScan < MaxNibble) {
5344 unsigned claimed = std::min(MaxNibble - lastScan, numWords);
5345 numWords -= claimed;
5346 lastScan += claimed;
5347 buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
5351 while (numWords >= MaxNibble) {
5352 buffer.push_back(MaxNibble << ScanShift);
5353 numWords -= MaxNibble;
5356 buffer.push_back(numWords << ScanShift);
5360 // One past the end of the last scan.
5361 unsigned endOfLastScanInWords = 0;
5362 const CharUnits WordSize = CGM.getPointerSize();
5364 // Consider all the scan requests.
5365 for (auto &request : IvarsInfo) {
5366 CharUnits beginOfScan = request.Offset - InstanceBegin;
5368 // Ignore scan requests that don't start at an even multiple of the
5369 // word size. We can't encode them.
5370 if ((beginOfScan % WordSize) != 0)
5373 // Ignore scan requests that start before the instance start.
5374 // This assumes that scans never span that boundary. The boundary
5375 // isn't the true start of the ivars, because in the fragile-ARC case
5376 // it's rounded up to word alignment, but the test above should leave
5377 // us ignoring that possibility.
5378 if (beginOfScan.isNegative()) {
5379 assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
5383 unsigned beginOfScanInWords = beginOfScan / WordSize;
5384 unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
5386 // If the scan starts some number of words after the last one ended,
5388 if (beginOfScanInWords > endOfLastScanInWords) {
5389 skip(beginOfScanInWords - endOfLastScanInWords);
5391 // Otherwise, start scanning where the last left off.
5393 beginOfScanInWords = endOfLastScanInWords;
5395 // If that leaves us with nothing to scan, ignore this request.
5396 if (beginOfScanInWords >= endOfScanInWords)
5400 // Scan to the end of the request.
5401 assert(beginOfScanInWords < endOfScanInWords);
5402 scan(endOfScanInWords - beginOfScanInWords);
5403 endOfLastScanInWords = endOfScanInWords;
5407 return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
5409 // For GC layouts, emit a skip to the end of the allocation so that we
5410 // have precise information about the entire thing. This isn't useful
5411 // or necessary for the ARC-style layout strings.
5412 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
5413 unsigned lastOffsetInWords =
5414 (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
5415 if (lastOffsetInWords > endOfLastScanInWords) {
5416 skip(lastOffsetInWords - endOfLastScanInWords);
5420 // Null terminate the string.
5421 buffer.push_back(0);
5423 auto *Entry = CGObjC.CreateCStringLiteral(
5424 reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName);
5425 return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
5445CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
5446 CharUnits beginOffset, CharUnits endOffset,
5447 bool ForStrongLayout, bool HasMRCWeakIvars) {
5448 // If this is MRC, and we're either building a strong layout or there
5449 // are no weak ivars, bail out early.
5450 llvm::Type *PtrTy = CGM.Int8PtrTy;
5451 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
5452 !CGM.getLangOpts().ObjCAutoRefCount &&
5453 (ForStrongLayout || !HasMRCWeakIvars))
5454 return llvm::Constant::getNullValue(PtrTy);
5456 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
5457 SmallVector<const ObjCIvarDecl *, 32> ivars;
5459 // GC layout strings include the complete object layout, possibly
5460 // inaccurately in the non-fragile ABI; the runtime knows how to fix this
5463 // ARC layout strings only include the class's ivars. In non-fragile
5464 // runtimes, that means starting at InstanceStart, rounded up to word
5465 // alignment. In fragile runtimes, there's no InstanceStart, so it means
5466 // starting at the offset of the first ivar, rounded up to word alignment.
5468 // MRC weak layout strings follow the ARC style.
5469 CharUnits baseOffset;
5470 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
5471 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin(); IVD;
5472 IVD = IVD->getNextIvar())
5473 ivars.push_back(IVD);
5475 if (isNonFragileABI()) {
5476 baseOffset = beginOffset; // InstanceStart
5477 } else if (!ivars.empty()) {
5479 CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
5481 baseOffset = CharUnits::Zero();
5484 baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
5486 CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
5488 baseOffset = CharUnits::Zero();
5492 return llvm::Constant::getNullValue(PtrTy);
5494 IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
5496 builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
5497 [&](const ObjCIvarDecl *ivar) -> CharUnits {
5498 return CharUnits::fromQuantity(
5499 ComputeIvarBaseOffset(CGM, OMD, ivar));
5502 if (!builder.hasBitmapData())
5503 return llvm::Constant::getNullValue(PtrTy);
5505 llvm::SmallVector<unsigned char, 4> buffer;
5506 llvm::Constant *C = builder.buildBitmap(*this, buffer);
5508 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
5509 printf("\n%
s ivar layout
for class '%s':
",
5510 ForStrongLayout ? "strong
" : "weak
",
5511 OMD->getClassInterface()->getName().str().c_str());
5512 builder.dump(buffer);
5517llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
5518 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
5519 // FIXME: Avoid std::string in "Sel.
getAsString()
"
5522 CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
5523 return getConstantGEP(VMContext, Entry, 0, 0);
5526// FIXME: Merge into a single cstring creation function.
5527llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
5528 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
5531llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
5532 std::string TypeStr;
5533 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
5535 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
5537 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
5538 return getConstantGEP(VMContext, Entry, 0, 0);
5541llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
5543 std::string TypeStr =
5544 CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
5546 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
5548 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
5549 return getConstantGEP(VMContext, Entry, 0, 0);
5552// FIXME: Merge into a single cstring creation function.
5553llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
5554 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
5556 Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
5557 return getConstantGEP(VMContext, Entry, 0, 0);
5560// FIXME: Merge into a single cstring creation function.
5561// FIXME: This Decl should be more precise.
5563CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
5564 const Decl *Container) {
5565 std::string TypeStr =
5566 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
5567 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
5570void CGObjCMac::FinishModule() {
5573 // Emit the dummy bodies for any protocols which were referenced but
5575 for (auto &entry : Protocols) {
5576 llvm::GlobalVariable *global = entry.second;
5577 if (global->hasInitializer())
5580 ConstantInitBuilder builder(CGM);
5581 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
5582 values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
5583 values.add(GetClassName(entry.first->getName()));
5584 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
5585 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5586 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5587 values.finishAndSetAsInitializer(global);
5588 CGM.addCompilerUsedGlobal(global);
5591 // Add assembler directives to add lazy undefined symbol references
5592 // for classes which are referenced but not defined. This is
5593 // important for correct linker interaction.
5595 // FIXME: It would be nice if we had an LLVM construct for this.
5596 if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
5597 CGM.getTriple().isOSBinFormatMachO()) {
5598 SmallString<256> Asm;
5599 Asm += CGM.getModule().getModuleInlineAsm();
5600 if (!Asm.empty() && Asm.back() != '\n')
5603 llvm::raw_svector_ostream OS(Asm);
5604 for (const auto *Sym : DefinedSymbols)
5605 OS << "\t.objc_class_name_
" << Sym->getName() << "=0\n
"
5606 << "\t.globl .objc_class_name_
" << Sym->getName() << "\n
";
5607 for (const auto *Sym : LazySymbols)
5608 OS << "\t.lazy_reference .objc_class_name_
" << Sym->getName() << "\n
";
5609 for (const auto &Category : DefinedCategoryNames)
5610 OS << "\t.objc_category_name_
" << Category << "=0\n
"
5611 << "\t.globl .objc_category_name_
" << Category << "\n
";
5613 CGM.getModule().setModuleInlineAsm(OS.str());
5617CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
5618 : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
5619 ObjCEmptyVtableVar(nullptr) {
5625ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
5626 : VMContext(cgm.getLLVMContext()), CGM(cgm) {
5627 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5628 ASTContext &Ctx = CGM.getContext();
5629 unsigned ProgramAS = CGM.getDataLayout().getProgramAddressSpace();
5631 ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
5633 LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
5634 Int8PtrTy = CGM.Int8PtrTy;
5635 Int8PtrProgramASTy = llvm::PointerType::get(CGM.getLLVMContext(), ProgramAS);
5636 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
5638 // arm64 targets use "int" ivar offset variables. All others,
5639 // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
5640 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
5641 IvarOffsetVarTy = IntTy;
5643 IvarOffsetVarTy = LongTy;
5645 ObjectPtrTy = cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
5646 PtrObjectPtrTy = llvm::PointerType::getUnqual(VMContext);
5648 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
5650 // I'm not sure I like this. The implicit coordination is a bit
5651 // gross. We should solve this in a reasonable fashion because this
5652 // is a pretty common task (match some runtime data structure with
5653 // an LLVM data structure).
5655 // FIXME: This is leaked.
5656 // FIXME: Merge with rewriter code?
5658 // struct _objc_super {
5662 RecordDecl *RD = RecordDecl::Create(
5663 Ctx, TagTypeKind::Struct, Ctx.getTranslationUnitDecl(), SourceLocation(),
5664 SourceLocation(), &Ctx.Idents.get("_objc_super
"));
5665 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5666 nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
5667 false, ICIS_NoInit));
5668 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5669 nullptr, Ctx.getObjCClassType(), nullptr,
5670 nullptr, false, ICIS_NoInit));
5671 RD->completeDefinition();
5673 SuperCTy = Ctx.getCanonicalTagType(RD);
5674 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
5676 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
5677 SuperPtrTy = llvm::PointerType::getUnqual(VMContext);
5681 // char *attributes;
5683 PropertyTy = llvm::StructType::create("struct._prop_t
", Int8PtrTy, Int8PtrTy);
5685 // struct _prop_list_t {
5686 // uint32_t entsize; // sizeof(struct _prop_t)
5687 // uint32_t count_of_properties;
5688 // struct _prop_t prop_list[count_of_properties];
5690 PropertyListTy = llvm::StructType::create(
5691 "struct._prop_list_t
", IntTy, IntTy, llvm::ArrayType::get(PropertyTy, 0));
5692 // struct _prop_list_t *
5693 PropertyListPtrTy = llvm::PointerType::getUnqual(VMContext);
5695 // struct _objc_method {
5697 // char *method_type;
5700 MethodTy = llvm::StructType::create("struct._objc_method
", SelectorPtrTy,
5701 Int8PtrTy, Int8PtrProgramASTy);
5703 // struct _objc_cache *
5704 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache
");
5705 CachePtrTy = llvm::PointerType::getUnqual(VMContext);
5708ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
5709 : ObjCCommonTypesHelper(cgm) {
5710 // struct _objc_method_description {
5714 MethodDescriptionTy = llvm::StructType::create(
5715 "struct._objc_method_description
", SelectorPtrTy, Int8PtrTy);
5717 // struct _objc_method_description_list {
5719 // struct _objc_method_description[1];
5721 MethodDescriptionListTy =
5722 llvm::StructType::create("struct._objc_method_description_list
", IntTy,
5723 llvm::ArrayType::get(MethodDescriptionTy, 0));
5725 // struct _objc_method_description_list *
5726 MethodDescriptionListPtrTy = llvm::PointerType::getUnqual(VMContext);
5728 // Protocol description structures
5730 // struct _objc_protocol_extension {
5731 // uint32_t size; // sizeof(struct _objc_protocol_extension)
5732 // struct _objc_method_description_list *optional_instance_methods;
5733 // struct _objc_method_description_list *optional_class_methods;
5734 // struct _objc_property_list *instance_properties;
5735 // const char ** extendedMethodTypes;
5736 // struct _objc_property_list *class_properties;
5738 ProtocolExtensionTy = llvm::StructType::create(
5739 "struct._objc_protocol_extension
", IntTy, MethodDescriptionListPtrTy,
5740 MethodDescriptionListPtrTy, PropertyListPtrTy, Int8PtrPtrTy,
5743 // struct _objc_protocol_extension *
5744 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(VMContext);
5746 // Handle construction of Protocol and ProtocolList types
5748 // struct _objc_protocol {
5749 // struct _objc_protocol_extension *isa;
5750 // char *protocol_name;
5751 // struct _objc_protocol **_objc_protocol_list;
5752 // struct _objc_method_description_list *instance_methods;
5753 // struct _objc_method_description_list *class_methods;
5755 ProtocolTy = llvm::StructType::create(
5756 {ProtocolExtensionPtrTy, Int8PtrTy,
5757 llvm::PointerType::getUnqual(VMContext), MethodDescriptionListPtrTy,
5758 MethodDescriptionListPtrTy},
5759 "struct._objc_protocol
");
5762 llvm::StructType::create({llvm::PointerType::getUnqual(VMContext), LongTy,
5763 llvm::ArrayType::get(ProtocolTy, 0)},
5764 "struct._objc_protocol_list
");
5766 // struct _objc_protocol_list *
5767 ProtocolListPtrTy = llvm::PointerType::getUnqual(VMContext);
5769 ProtocolPtrTy = llvm::PointerType::getUnqual(VMContext);
5771 // Class description structures
5773 // struct _objc_ivar {
5778 IvarTy = llvm::StructType::create("struct._objc_ivar
", Int8PtrTy, Int8PtrTy,
5781 // struct _objc_ivar_list *
5782 IvarListTy = llvm::StructType::create(VMContext, "struct._objc_ivar_list
");
5783 IvarListPtrTy = llvm::PointerType::getUnqual(VMContext);
5785 // struct _objc_method_list *
5787 llvm::StructType::create(VMContext, "struct._objc_method_list
");
5788 MethodListPtrTy = llvm::PointerType::getUnqual(VMContext);
5790 // struct _objc_class_extension *
5791 ClassExtensionTy = llvm::StructType::create(
5792 "struct._objc_class_extension
", IntTy, Int8PtrTy, PropertyListPtrTy);
5793 ClassExtensionPtrTy = llvm::PointerType::getUnqual(VMContext);
5795 // struct _objc_class {
5797 // Class super_class;
5801 // long instance_size;
5802 // struct _objc_ivar_list *ivars;
5803 // struct _objc_method_list *methods;
5804 // struct _objc_cache *cache;
5805 // struct _objc_protocol_list *protocols;
5806 // char *ivar_layout;
5807 // struct _objc_class_ext *ext;
5809 ClassTy = llvm::StructType::create(
5810 {llvm::PointerType::getUnqual(VMContext),
5811 llvm::PointerType::getUnqual(VMContext), Int8PtrTy, LongTy, LongTy,
5812 LongTy, IvarListPtrTy, MethodListPtrTy, CachePtrTy, ProtocolListPtrTy,
5813 Int8PtrTy, ClassExtensionPtrTy},
5814 "struct._objc_class
");
5816 ClassPtrTy = llvm::PointerType::getUnqual(VMContext);
5818 // struct _objc_category {
5819 // char *category_name;
5820 // char *class_name;
5821 // struct _objc_method_list *instance_method;
5822 // struct _objc_method_list *class_method;
5823 // struct _objc_protocol_list *protocols;
5824 // uint32_t size; // sizeof(struct _objc_category)
5825 // struct _objc_property_list *instance_properties;// category's @property
5826 // struct _objc_property_list *class_properties;
5828 CategoryTy = llvm::StructType::create(
5829 "struct._objc_category
", Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5830 MethodListPtrTy, ProtocolListPtrTy, IntTy, PropertyListPtrTy,
5833 // Global metadata structures
5835 // struct _objc_symtab {
5836 // long sel_ref_cnt;
5838 // short cls_def_cnt;
5839 // short cat_def_cnt;
5840 // char *defs[cls_def_cnt + cat_def_cnt];
5842 SymtabTy = llvm::StructType::create("struct._objc_symtab
", LongTy,
5843 SelectorPtrTy, ShortTy, ShortTy,
5844 llvm::ArrayType::get(Int8PtrTy, 0));
5845 SymtabPtrTy = llvm::PointerType::getUnqual(VMContext);
5847 // struct _objc_module {
5849 // long size; // sizeof(struct _objc_module)
5851 // struct _objc_symtab* symtab;
5853 ModuleTy = llvm::StructType::create("struct._objc_module
", LongTy, LongTy,
5854 Int8PtrTy, SymtabPtrTy);
5856 // FIXME: This is the size of the setjmp buffer and should be target
5857 // specific. 18 is what's used on 32-bit X86.
5858 uint64_t SetJmpBufferSize = 18;
5861 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
5863 ExceptionDataTy = llvm::StructType::create(
5864 "struct._objc_exception_data
",
5865 llvm::ArrayType::get(CGM.Int32Ty, SetJmpBufferSize), StackPtrTy);
5868ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(
5869 CodeGen::CodeGenModule &cgm)
5870 : ObjCCommonTypesHelper(cgm) {
5871 // struct _method_list_t {
5872 // uint32_t entsize; // sizeof(struct _objc_method)
5873 // uint32_t method_count;
5874 // struct _objc_method method_list[method_count];
5877 llvm::StructType::create("struct.__method_list_t
", IntTy, IntTy,
5878 llvm::ArrayType::get(MethodTy, 0));
5879 // struct method_list_t *
5880 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);
5882 // struct _protocol_t {
5884 // const char * const protocol_name;
5885 // const struct _protocol_list_t * protocol_list; // super protocols
5886 // const struct method_list_t * const instance_methods;
5887 // const struct method_list_t * const class_methods;
5888 // const struct method_list_t *optionalInstanceMethods;
5889 // const struct method_list_t *optionalClassMethods;
5890 // const struct _prop_list_t * properties;
5891 // const uint32_t size; // sizeof(struct _protocol_t)
5892 // const uint32_t flags; // = 0
5893 // const char ** extendedMethodTypes;
5894 // const char *demangledName;
5895 // const struct _prop_list_t * class_properties;
5898 ProtocolnfABITy = llvm::StructType::create(
5899 "struct._protocol_t
", ObjectPtrTy, Int8PtrTy,
5900 llvm::PointerType::getUnqual(VMContext), MethodListnfABIPtrTy,
5901 MethodListnfABIPtrTy, MethodListnfABIPtrTy, MethodListnfABIPtrTy,
5902 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy, Int8PtrTy,
5905 // struct _protocol_t*
5906 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);
5908 // struct _protocol_list_t {
5909 // long protocol_count; // Note, this is 32/64 bit
5910 // struct _protocol_t *[protocol_count];
5912 ProtocolListnfABITy = llvm::StructType::create(
5913 {LongTy, llvm::ArrayType::get(ProtocolnfABIPtrTy, 0)},
5914 "struct._objc_protocol_list
");
5916 // struct _objc_protocol_list*
5917 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);
5920 // unsigned [long] int *offset; // pointer to ivar offset location
5923 // uint32_t alignment;
5926 IvarnfABITy = llvm::StructType::create(
5927 "struct._ivar_t
", llvm::PointerType::getUnqual(VMContext), Int8PtrTy,
5928 Int8PtrTy, IntTy, IntTy);
5930 // struct _ivar_list_t {
5931 // uint32 entsize; // sizeof(struct _ivar_t)
5933 // struct _iver_t list[count];
5936 llvm::StructType::create("struct._ivar_list_t
", IntTy, IntTy,
5937 llvm::ArrayType::get(IvarnfABITy, 0));
5939 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);
5941 // struct _class_ro_t {
5942 // uint32_t const flags;
5943 // uint32_t const instanceStart;
5944 // uint32_t const instanceSize;
5945 // uint32_t const reserved; // only when building for 64bit targets
5946 // const uint8_t * const ivarLayout;
5947 // const char *const name;
5948 // const struct _method_list_t * const baseMethods;
5949 // const struct _objc_protocol_list *const baseProtocols;
5950 // const struct _ivar_list_t *const ivars;
5951 // const uint8_t * const weakIvarLayout;
5952 // const struct _prop_list_t * const properties;
5955 // FIXME. Add 'reserved' field in 64bit abi mode!
5956 ClassRonfABITy = llvm::StructType::create(
5957 "struct._class_ro_t
", IntTy, IntTy, IntTy, Int8PtrTy, Int8PtrTy,
5958 MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, IvarListnfABIPtrTy,
5959 Int8PtrTy, PropertyListPtrTy);
5961 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
5962 ImpnfABITy = CGM.UnqualPtrTy;
5964 // struct _class_t {
5965 // struct _class_t *isa;
5966 // struct _class_t * const superclass;
5969 // struct class_ro_t *ro;
5972 ClassnfABITy = llvm::StructType::create(
5973 {llvm::PointerType::getUnqual(VMContext),
5974 llvm::PointerType::getUnqual(VMContext), CachePtrTy,
5975 llvm::PointerType::getUnqual(VMContext),
5976 llvm::PointerType::getUnqual(VMContext)},
5979 // LLVM for struct _class_t *
5980 ClassnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);
5982 // struct _category_t {
5983 // const char * const name;
5984 // struct _class_t *const cls;
5985 // const struct _method_list_t * const instance_methods;
5986 // const struct _method_list_t * const class_methods;
5987 // const struct _protocol_list_t * const protocols;
5988 // const struct _prop_list_t * const properties;
5989 // const struct _prop_list_t * const class_properties;
5990 // const uint32_t size;
5992 CategorynfABITy = llvm::StructType::create(
5993 "struct._category_t
", Int8PtrTy, ClassnfABIPtrTy, MethodListnfABIPtrTy,
5994 MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, PropertyListPtrTy,
5995 PropertyListPtrTy, IntTy);
5997 // New types for nonfragile abi messaging.
5998 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5999 ASTContext &Ctx = CGM.getContext();
6001 // MessageRefTy - LLVM for:
6002 // struct _message_ref_t {
6007 // First the clang type for struct _message_ref_t
6008 RecordDecl *RD = RecordDecl::Create(
6009 Ctx, TagTypeKind::Struct, Ctx.getTranslationUnitDecl(), SourceLocation(),
6010 SourceLocation(), &Ctx.Idents.get("_message_ref_t
"));
6011 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6012 nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false,
6014 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
6015 nullptr, Ctx.getObjCSelType(), nullptr, nullptr,
6016 false, ICIS_NoInit));
6017 RD->completeDefinition();
6019 MessageRefCTy = Ctx.getCanonicalTagType(RD);
6020 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
6021 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
6023 // MessageRefPtrTy - LLVM for struct _message_ref_t*
6024 MessageRefPtrTy = llvm::PointerType::getUnqual(VMContext);
6026 // SuperMessageRefTy - LLVM for:
6027 // struct _super_message_ref_t {
6028 // SUPER_IMP messenger;
6031 SuperMessageRefTy = llvm::StructType::create("struct._super_message_ref_t
",
6032 ImpnfABITy, SelectorPtrTy);
6034 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
6035 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(VMContext);
6037 // struct objc_typeinfo {
6038 // const void** vtable; // objc_ehtype_vtable + 2
6039 // const char* name; // c++ typeinfo string
6042 EHTypeTy = llvm::StructType::create("struct._objc_typeinfo
",
6043 llvm::PointerType::getUnqual(VMContext),
6044 Int8PtrTy, ClassnfABIPtrTy);
6045 EHTypePtrTy = llvm::PointerType::getUnqual(VMContext);
6048llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
6049 FinishNonFragileABIModule();
6054void CGObjCNonFragileABIMac::AddModuleClassList(
6055 ArrayRef<llvm::GlobalValue *> Container, StringRef SymbolName,
6056 StringRef SectionName) {
6057 unsigned NumClasses = Container.size();
6062 SmallVector<llvm::Constant *, 8> Symbols(NumClasses);
6063 for (unsigned i = 0; i < NumClasses; i++)
6064 Symbols[i] = Container[i];
6066 llvm::Constant *Init = llvm::ConstantArray::get(
6067 llvm::ArrayType::get(ObjCTypes.Int8PtrTy, Symbols.size()), Symbols);
6069 // Section name is obtained by calling GetSectionName, which returns
6070 // sections in the __DATA segment on MachO.
6071 assert((!CGM.getTriple().isOSBinFormatMachO() ||
6072 SectionName.starts_with("__DATA
")) &&
6073 "SectionName expected to start with __DATA on MachO
");
6074 llvm::GlobalVariable *GV = new llvm::GlobalVariable(
6075 CGM.getModule(), Init->getType(), false,
6076 llvm::GlobalValue::PrivateLinkage, Init, SymbolName);
6077 GV->setAlignment(CGM.getDataLayout().getABITypeAlign(Init->getType()));
6078 GV->setSection(SectionName);
6079 CGM.addCompilerUsedGlobal(GV);
6082void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
6083 // nonfragile abi has no module definition.
6085 // Build list of all implemented class addresses in array
6086 // L_OBJC_LABEL_CLASS_$.
6088 for (unsigned i = 0, NumClasses = ImplementedClasses.size(); i < NumClasses;
6090 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
6092 if (ObjCImplementationDecl *IMP = ID->getImplementation())
6093 // We are implementing a weak imported interface. Give it external linkage
6094 if (ID->isWeakImported() && !IMP->isWeakImported()) {
6095 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
6096 DefinedMetaClasses[i]->setLinkage(
6097 llvm::GlobalVariable::ExternalLinkage);
6102 DefinedClasses, "OBJC_LABEL_CLASS_$
",
6103 GetSectionName("__objc_classlist
", "regular,no_dead_strip
"));
6106 DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$
",
6107 GetSectionName("__objc_nlclslist
", "regular,no_dead_strip
"));
6109 // Build list of all implemented category addresses in array
6110 // L_OBJC_LABEL_CATEGORY_$.
6111 AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$
",
6112 GetSectionName("__objc_catlist
", "regular,no_dead_strip
"));
6114 DefinedStubCategories, "OBJC_LABEL_STUB_CATEGORY_$
",
6115 GetSectionName("__objc_catlist2
", "regular,no_dead_strip
"));
6117 DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$
",
6118 GetSectionName("__objc_nlcatlist
", "regular,no_dead_strip
"));
6127bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
6128 // At various points we've experimented with using vtable-based
6129 // dispatch for all methods.
6130 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
6131 case CodeGenOptions::Legacy:
6133 case CodeGenOptions::NonLegacy:
6135 case CodeGenOptions::Mixed:
6139 // If so, see whether this selector is in the white-list of things which must
6140 // use the new dispatch convention. We lazily build a dense set for this.
6141 if (VTableDispatchMethods.empty()) {
6142 VTableDispatchMethods.insert(GetNullarySelector("alloc
"));
6143 VTableDispatchMethods.insert(GetNullarySelector("class"));
6144 VTableDispatchMethods.insert(GetNullarySelector("self
"));
6145 VTableDispatchMethods.insert(GetNullarySelector("isFlipped
"));
6146 VTableDispatchMethods.insert(GetNullarySelector("length"));
6147 VTableDispatchMethods.insert(GetNullarySelector("count
"));
6149 // These are vtable-based if GC is disabled.
6150 // Optimistically use vtable dispatch for hybrid compiles.
6151 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
6152 VTableDispatchMethods.insert(GetNullarySelector("retain
"));
6153 VTableDispatchMethods.insert(GetNullarySelector("release
"));
6154 VTableDispatchMethods.insert(GetNullarySelector("autorelease
"));
6157 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone
"));
6158 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass
"));
6159 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector
"));
6160 VTableDispatchMethods.insert(GetUnarySelector("objectForKey
"));
6161 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex
"));
6162 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString
"));
6163 VTableDispatchMethods.insert(GetUnarySelector("isEqual
"));
6165 // These are vtable-based if GC is enabled.
6166 // Optimistically use vtable dispatch for hybrid compiles.
6167 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
6168 VTableDispatchMethods.insert(GetNullarySelector("hash
"));
6169 VTableDispatchMethods.insert(GetUnarySelector("addObject
"));
6171 // "countByEnumeratingWithState:objects:count
"
6172 const IdentifierInfo *KeyIdents[] = {
6173 &CGM.getContext().Idents.get("countByEnumeratingWithState
"),
6174 &CGM.getContext().Idents.get("objects
"),
6175 &CGM.getContext().Idents.get("count
")};
6176 VTableDispatchMethods.insert(
6177 CGM.getContext().Selectors.getSelector(3, KeyIdents));
6181 return VTableDispatchMethods.count(Sel);
6199llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassRoTInitializer(
6200 unsigned flags, unsigned InstanceStart, unsigned InstanceSize,
6201 const ObjCImplementationDecl *ID) {
6202 std::string ClassName = std::string(ID->getObjCRuntimeNameAsString());
6204 CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
6205 CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
6207 bool hasMRCWeak = false;
6208 if (CGM.getLangOpts().ObjCAutoRefCount)
6209 flags |= NonFragileABI_Class_CompiledByARC;
6210 else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
6211 flags |= NonFragileABI_Class_HasMRCWeakIvars;
6213 ConstantInitBuilder builder(CGM);
6214 auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy);
6216 values.addInt(ObjCTypes.IntTy, flags);
6217 values.addInt(ObjCTypes.IntTy, InstanceStart);
6218 values.addInt(ObjCTypes.IntTy, InstanceSize);
6219 values.add((flags & NonFragileABI_Class_Meta)
6220 ? GetIvarLayoutName(nullptr, ObjCTypes)
6221 : BuildStrongIvarLayout(ID, beginInstance, endInstance));
6222 values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
6224 // const struct _method_list_t * const baseMethods;
6225 SmallVector<const ObjCMethodDecl *, 16> methods;
6226 if (flags & NonFragileABI_Class_Meta) {
6227 for (const auto *MD : ID->class_methods())
6228 if (!MD->isDirectMethod())
6229 methods.push_back(MD);
6231 for (const auto *MD : ID->instance_methods())
6232 if (!MD->isDirectMethod())
6233 methods.push_back(MD);
6236 llvm::Constant *MethListPtr = emitMethodList(
6237 ID->getObjCRuntimeNameAsString(),
6238 (flags & NonFragileABI_Class_Meta) ? MethodListType::ClassMethods
6239 : MethodListType::InstanceMethods,
6242 const PointerAuthSchema &MethListSchema =
6243 CGM.getCodeGenOpts().PointerAuth.ObjCMethodListPointer;
6244 if (!MethListPtr->isNullValue())
6245 values.addSignedPointer(MethListPtr, MethListSchema, GlobalDecl(),
6248 values.add(MethListPtr);
6250 const ObjCInterfaceDecl *OID = ID->getClassInterface();
6251 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer
");
6252 values.add(EmitProtocolList("_OBJC_CLASS_PROTOCOLS_$_
" +
6253 OID->getObjCRuntimeNameAsString(),
6254 OID->all_referenced_protocol_begin(),
6255 OID->all_referenced_protocol_end()));
6257 if (flags & NonFragileABI_Class_Meta) {
6258 values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy);
6259 values.add(GetIvarLayoutName(nullptr, ObjCTypes));
6260 values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_
" +
6261 ID->getObjCRuntimeNameAsString(),
6262 ID, ID->getClassInterface(), ObjCTypes, true));
6264 values.add(EmitIvarList(ID));
6265 values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak));
6266 values.add(EmitPropertyList("_OBJC_$_PROP_LIST_
" +
6267 ID->getObjCRuntimeNameAsString(),
6268 ID, ID->getClassInterface(), ObjCTypes, false));
6271 llvm::SmallString<64> roLabel;
6272 llvm::raw_svector_ostream(roLabel)
6273 << ((flags & NonFragileABI_Class_Meta) ? "_OBJC_METACLASS_RO_$_
"
6274 : "_OBJC_CLASS_RO_$_
")
6277 return finishAndCreateGlobal(values, roLabel, CGM);
6290llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassObject(
6291 const ObjCInterfaceDecl *CI, bool isMetaclass, llvm::Constant *IsAGV,
6292 llvm::Constant *SuperClassGV, llvm::Constant *ClassRoGV,
6293 bool HiddenVisibility) {
6294 ConstantInitBuilder builder(CGM);
6295 auto values = builder.beginStruct(ObjCTypes.ClassnfABITy);
6296 const PointerAuthOptions &PointerAuthOpts = CGM.getCodeGenOpts().PointerAuth;
6297 values.addSignedPointer(IsAGV, PointerAuthOpts.ObjCIsaPointers, GlobalDecl(),
6300 values.addSignedPointer(SuperClassGV, PointerAuthOpts.ObjCSuperPointers,
6301 GlobalDecl(), QualType());
6303 values.addNullPointer(ObjCTypes.ClassnfABIPtrTy);
6305 values.add(ObjCEmptyCacheVar);
6306 values.add(ObjCEmptyVtableVar);
6308 values.addSignedPointer(ClassRoGV, PointerAuthOpts.ObjCClassROPointers,
6309 GlobalDecl(), QualType());
6311 llvm::GlobalVariable *GV = cast<llvm::GlobalVariable>(
6312 GetClassGlobal(CI, isMetaclass, ForDefinition));
6313 values.finishAndSetAsInitializer(GV);
6315 if (CGM.getTriple().isOSBinFormatMachO())
6316 GV->setSection("__DATA, __objc_data
");
6317 GV->setAlignment(CGM.getDataLayout().getABITypeAlign(ObjCTypes.ClassnfABITy));
6318 if (!CGM.getTriple().isOSBinFormatCOFF())
6319 if (HiddenVisibility)
6320 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6324bool CGObjCNonFragileABIMac::ImplementationIsNonLazy(
6325 const ObjCImplDecl *OD) const {
6326 return OD->getClassMethod(GetNullarySelector("load
")) != nullptr ||
6327 OD->getClassInterface()->hasAttr<ObjCNonLazyClassAttr>() ||
6328 OD->hasAttr<ObjCNonLazyClassAttr>();
6331void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
6332 uint32_t &InstanceStart,
6333 uint32_t &InstanceSize) {
6334 const ASTRecordLayout &RL =
6335 CGM.getContext().getASTObjCInterfaceLayout(OID->getClassInterface());
6337 // InstanceSize is really instance end.
6338 InstanceSize = RL.getDataSize().getQuantity();
6340 // If there are no fields, the start is the same as the end.
6341 if (!RL.getFieldCount())
6342 InstanceStart = InstanceSize;
6344 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
6347static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM,
6349 IdentifierInfo &II = CGM.getContext().Idents.get(Name);
6350 TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
6351 DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
6353 const VarDecl *VD = nullptr;
6354 for (const auto *Result : DC->lookup(&II))
6355 if ((VD = dyn_cast<VarDecl>(Result)))
6359 return llvm::GlobalValue::DLLImportStorageClass;
6360 if (VD->hasAttr<DLLExportAttr>())
6361 return llvm::GlobalValue::DLLExportStorageClass;
6362 if (VD->hasAttr<DLLImportAttr>())
6363 return llvm::GlobalValue::DLLImportStorageClass;
6364 return llvm::GlobalValue::DefaultStorageClass;
6367void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
6368 if (!ObjCEmptyCacheVar) {
6369 ObjCEmptyCacheVar = new llvm::GlobalVariable(
6370 CGM.getModule(), ObjCTypes.CacheTy, false,
6371 llvm::GlobalValue::ExternalLinkage, nullptr, "_objc_empty_cache
");
6372 if (CGM.getTriple().isOSBinFormatCOFF())
6373 ObjCEmptyCacheVar->setDLLStorageClass(
6374 getStorage(CGM, "_objc_empty_cache
"));
6376 // Only OS X with deployment version <10.9 use the empty vtable symbol
6377 const llvm::Triple &Triple = CGM.getTarget().getTriple();
6378 if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9))
6379 ObjCEmptyVtableVar = new llvm::GlobalVariable(
6380 CGM.getModule(), ObjCTypes.ImpnfABITy, false,
6381 llvm::GlobalValue::ExternalLinkage, nullptr, "_objc_empty_vtable
");
6383 ObjCEmptyVtableVar = llvm::ConstantPointerNull::get(CGM.UnqualPtrTy);
6386 // FIXME: Is this correct (that meta class size is never computed)?
6387 uint32_t InstanceStart =
6388 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
6389 uint32_t InstanceSize = InstanceStart;
6390 uint32_t flags = NonFragileABI_Class_Meta;
6392 llvm::Constant *SuperClassGV, *IsAGV;
6394 const auto *CI = ID->getClassInterface();
6395 assert(CI && "CGObjCNonFragileABIMac::GenerateClass -
class is 0
");
6397 // Build the flags for the metaclass.
6398 bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF())
6399 ? !CI->hasAttr<DLLExportAttr>()
6400 : CI->getVisibility() == HiddenVisibility;
6402 flags |= NonFragileABI_Class_Hidden;
6404 // FIXME: why is this flag set on the metaclass?
6405 // ObjC metaclasses have no fields and don't really get constructed.
6406 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
6407 flags |= NonFragileABI_Class_HasCXXStructors;
6408 if (!ID->hasNonZeroConstructors())
6409 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
6412 if (!CI->getSuperClass()) {
6414 flags |= NonFragileABI_Class_Root;
6416 SuperClassGV = GetClassGlobal(CI, /*metaclass*/ false, NotForDefinition);
6417 IsAGV = GetClassGlobal(CI, /*metaclass*/ true, NotForDefinition);
6419 // Has a root. Current class is not a root.
6420 const ObjCInterfaceDecl *Root = ID->getClassInterface();
6421 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
6424 const auto *Super = CI->getSuperClass();
6425 IsAGV = GetClassGlobal(Root, /*metaclass*/ true, NotForDefinition);
6426 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ true, NotForDefinition);
6429 llvm::GlobalVariable *CLASS_RO_GV =
6430 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
6432 llvm::GlobalVariable *MetaTClass = BuildClassObject(
6433 CI, /*metaclass*/ true, IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden);
6434 CGM.setGVProperties(MetaTClass, CI);
6435 DefinedMetaClasses.push_back(MetaTClass);
6437 // Metadata for the class
6440 flags |= NonFragileABI_Class_Hidden;
6442 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
6443 flags |= NonFragileABI_Class_HasCXXStructors;
6445 // Set a flag to enable a runtime optimization when a class has
6446 // fields that require destruction but which don't require
6447 // anything except zero-initialization during construction. This
6448 // is most notably true of __strong and __weak types, but you can
6449 // also imagine there being C++ types with non-trivial default
6450 // constructors that merely set all fields to null.
6451 if (!ID->hasNonZeroConstructors())
6452 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
6455 if (hasObjCExceptionAttribute(CGM.getContext(), CI))
6456 flags |= NonFragileABI_Class_Exception;
6458 if (!CI->getSuperClass()) {
6459 flags |= NonFragileABI_Class_Root;
6460 SuperClassGV = nullptr;
6462 // Has a root. Current class is not a root.
6463 const auto *Super = CI->getSuperClass();
6464 SuperClassGV = GetClassGlobal(Super, /*metaclass*/ false, NotForDefinition);
6467 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
6469 BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);
6471 llvm::GlobalVariable *ClassMD =
6472 BuildClassObject(CI, /*metaclass*/ false, MetaTClass, SuperClassGV,
6473 CLASS_RO_GV, classIsHidden);
6474 CGM.setGVProperties(ClassMD, CI);
6475 DefinedClasses.push_back(ClassMD);
6476 ImplementedClasses.push_back(CI);
6478 // Determine if this class is also "non-lazy
".
6479 if (ImplementationIsNonLazy(ID))
6480 DefinedNonLazyClasses.push_back(ClassMD);
6482 // Force the definition of the EHType if necessary.
6483 if (flags & NonFragileABI_Class_Exception)
6484 (void)GetInterfaceEHType(CI, ForDefinition);
6485 // Make sure method definition entries are all clear for next implementation.
6486 MethodDefinitions.clear();
6498CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
6499 const ObjCProtocolDecl *PD) {
6501 // This routine is called for @protocol only. So, we must build definition
6502 // of protocol's meta-data (not a reference to it!)
6503 assert(!PD->isNonRuntimeProtocol() &&
6504 "attempting to get a protocol ref to a
static protocol.
");
6505 llvm::Constant *Init = GetOrEmitProtocol(PD);
6507 std::string ProtocolName("_OBJC_PROTOCOL_REFERENCE_$_
");
6508 ProtocolName += PD->getObjCRuntimeNameAsString();
6510 CharUnits Align = CGF.getPointerAlign();
6512 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
6514 return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
6515 PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
6516 llvm::GlobalValue::WeakAnyLinkage, Init,
6519 GetSectionName("__objc_protorefs
", "coalesced,no_dead_strip
"));
6520 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6521 PTGV->setAlignment(Align.getAsAlign());
6522 if (!CGM.getTriple().isOSBinFormatMachO())
6523 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName));
6524 CGM.addUsedGlobal(PTGV);
6525 return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
6540void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
6541 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
6542 const char *Prefix = "_OBJC_$_CATEGORY_
";
6544 llvm::SmallString<64> ExtCatName(Prefix);
6545 ExtCatName += Interface->getObjCRuntimeNameAsString();
6546 ExtCatName += "_$_
";
6547 ExtCatName += OCD->getNameAsString();
6549 ConstantInitBuilder builder(CGM);
6550 auto values = builder.beginStruct(ObjCTypes.CategorynfABITy);
6551 values.add(GetClassName(OCD->getIdentifier()->getName()));
6552 // meta-class entry symbol
6553 values.add(GetClassGlobal(Interface, /*metaclass*/ false, NotForDefinition));
6554 std::string listName =
6555 (Interface->getObjCRuntimeNameAsString() + "_$_
" + OCD->getName()).str();
6557 SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
6558 SmallVector<const ObjCMethodDecl *, 8> classMethods;
6559 for (const auto *MD : OCD->methods()) {
6560 if (MD->isDirectMethod())
6562 if (MD->isInstanceMethod()) {
6563 instanceMethods.push_back(MD);
6565 classMethods.push_back(MD);
6569 llvm::Constant *InstanceMethodList = emitMethodList(
6570 listName, MethodListType::CategoryInstanceMethods, instanceMethods);
6571 const PointerAuthSchema &MethListSchema =
6572 CGM.getCodeGenOpts().PointerAuth.ObjCMethodListPointer;
6573 if (!InstanceMethodList->isNullValue())
6574 values.addSignedPointer(InstanceMethodList, MethListSchema, GlobalDecl(),
6577 values.add(InstanceMethodList);
6579 llvm::Constant *ClassMethodList = emitMethodList(
6580 listName, MethodListType::CategoryClassMethods, classMethods);
6581 if (!ClassMethodList->isNullValue())
6582 values.addSignedPointer(ClassMethodList, MethListSchema, GlobalDecl(),
6585 values.add(ClassMethodList);
6587 // Keep track of whether we have actual metadata to emit.
6588 bool isEmptyCategory =
6589 InstanceMethodList->isNullValue() && ClassMethodList->isNullValue();
6591 const ObjCCategoryDecl *Category =
6592 Interface->FindCategoryDeclaration(OCD->getIdentifier());
6594 SmallString<256> ExtName;
6595 llvm::raw_svector_ostream(ExtName)
6596 << Interface->getObjCRuntimeNameAsString() << "_$_
" << OCD->getName();
6598 EmitProtocolList("_OBJC_CATEGORY_PROTOCOLS_$_
" +
6599 Interface->getObjCRuntimeNameAsString() + "_$_
" +
6600 Category->getName(),
6601 Category->protocol_begin(), Category->protocol_end());
6602 auto propertyList = EmitPropertyList("_OBJC_$_PROP_LIST_
" + ExtName.str(),
6603 OCD, Category, ObjCTypes, false);
6604 auto classPropertyList =
6605 EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_
" + ExtName.str(), OCD,
6606 Category, ObjCTypes, true);
6607 values.add(protocolList);
6608 values.add(propertyList);
6609 values.add(classPropertyList);
6610 isEmptyCategory &= protocolList->isNullValue() &&
6611 propertyList->isNullValue() &&
6612 classPropertyList->isNullValue();
6614 values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy);
6615 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
6616 values.addNullPointer(ObjCTypes.PropertyListPtrTy);
6619 if (isEmptyCategory) {
6620 // Empty category, don't emit any metadata.
6622 MethodDefinitions.clear();
6627 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
6628 values.addInt(ObjCTypes.IntTy, Size);
6630 llvm::GlobalVariable *GCATV =
6631 finishAndCreateGlobal(values, ExtCatName.str(), CGM);
6632 CGM.addCompilerUsedGlobal(GCATV);
6633 if (Interface->hasAttr<ObjCClassStubAttr>())
6634 DefinedStubCategories.push_back(GCATV);
6636 DefinedCategories.push_back(GCATV);
6638 // Determine if this category is also "non-lazy
".
6639 if (ImplementationIsNonLazy(OCD))
6640 DefinedNonLazyCategories.push_back(GCATV);
6641 // method definition entries must be clear for next implementation.
6642 MethodDefinitions.clear();
6654void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
6655 const ObjCMethodDecl *MD,
6657 auto method = builder.beginStruct(ObjCTypes.MethodTy);
6658 method.add(GetMethodVarName(MD->getSelector()));
6659 method.add(GetMethodVarType(MD));
6662 // Protocol methods have no implementation. So, this entry is always NULL.
6663 method.addNullPointer(ObjCTypes.Int8PtrProgramASTy);
6665 llvm::Function *fn = GetMethodDefinition(MD);
6666 assert(fn && "no definition
for method?
");
6667 if (const PointerAuthSchema &Schema =
6668 CGM.getCodeGenOpts().PointerAuth.ObjCMethodListFunctionPointers) {
6669 llvm::Constant *Bitcast =
6670 llvm::ConstantExpr::getBitCast(fn, ObjCTypes.Int8PtrProgramASTy);
6671 method.addSignedPointer(Bitcast, Schema, GlobalDecl(), QualType());
6676 method.finishAndAddTo(builder);
6687llvm::Constant *CGObjCNonFragileABIMac::emitMethodList(
6688 Twine name, MethodListType kind, ArrayRef<const ObjCMethodDecl *> methods) {
6689 // Return null for empty list.
6690 if (methods.empty())
6691 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
6696 case MethodListType::CategoryInstanceMethods:
6697 prefix = "_OBJC_$_CATEGORY_INSTANCE_METHODS_
";
6698 forProtocol = false;
6700 case MethodListType::CategoryClassMethods:
6701 prefix = "_OBJC_$_CATEGORY_CLASS_METHODS_
";
6702 forProtocol = false;
6704 case MethodListType::InstanceMethods:
6705 prefix = "_OBJC_$_INSTANCE_METHODS_
";
6706 forProtocol = false;
6708 case MethodListType::ClassMethods:
6709 prefix = "_OBJC_$_CLASS_METHODS_
";
6710 forProtocol = false;
6713 case MethodListType::ProtocolInstanceMethods:
6714 prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_
";
6717 case MethodListType::ProtocolClassMethods:
6718 prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_
";
6721 case MethodListType::OptionalProtocolInstanceMethods:
6722 prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_
";
6725 case MethodListType::OptionalProtocolClassMethods:
6726 prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_
";
6731 ConstantInitBuilder builder(CGM);
6732 auto values = builder.beginStruct();
6734 // sizeof(struct _objc_method)
6735 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
6736 values.addInt(ObjCTypes.IntTy, Size);
6738 values.addInt(ObjCTypes.IntTy, methods.size());
6739 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
6740 for (auto MD : methods)
6741 emitMethodConstant(methodArray, MD, forProtocol);
6742 methodArray.finishAndAddTo(values);
6744 llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM);
6745 CGM.addCompilerUsedGlobal(GV);
6751llvm::GlobalVariable *
6752CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6753 const ObjCIvarDecl *Ivar) {
6754 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
6755 llvm::SmallString<64> Name("OBJC_IVAR_$_
");
6756 Name += Container->getObjCRuntimeNameAsString();
6758 Name += Ivar->getName();
6759 llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name);
6760 if (!IvarOffsetGV) {
6761 IvarOffsetGV = new llvm::GlobalVariable(
6762 CGM.getModule(), ObjCTypes.IvarOffsetVarTy, false,
6763 llvm::GlobalValue::ExternalLinkage, nullptr, Name.str());
6764 if (CGM.getTriple().isOSBinFormatCOFF()) {
6765 bool IsPrivateOrPackage =
6766 Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6767 Ivar->getAccessControl() == ObjCIvarDecl::Package;
6769 const ObjCInterfaceDecl *ContainingID = Ivar->getContainingInterface();
6771 if (ContainingID->hasAttr<DLLImportAttr>())
6772 IvarOffsetGV->setDLLStorageClass(
6773 llvm::GlobalValue::DLLImportStorageClass);
6774 else if (ContainingID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage)
6775 IvarOffsetGV->setDLLStorageClass(
6776 llvm::GlobalValue::DLLExportStorageClass);
6779 return IvarOffsetGV;
6783CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6784 const ObjCIvarDecl *Ivar,
6785 unsigned long int Offset) {
6786 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
6787 IvarOffsetGV->setInitializer(
6788 llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset));
6789 IvarOffsetGV->setAlignment(
6790 CGM.getDataLayout().getABITypeAlign(ObjCTypes.IvarOffsetVarTy));
6792 if (!CGM.getTriple().isOSBinFormatCOFF()) {
6793 // FIXME: This matches gcc, but shouldn't the visibility be set on the use
6794 // as well (i.e., in ObjCIvarOffsetVariable).
6795 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6796 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
6797 ID->getVisibility() == HiddenVisibility)
6798 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
6800 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
6803 // If ID's layout is known, then make the global constant. This serves as a
6804 // useful assertion: we'll never use this variable to calculate ivar offsets,
6805 // so if the runtime tries to patch it then we should crash.
6806 if (isClassLayoutKnownStatically(ID))
6807 IvarOffsetGV->setConstant(true);
6809 if (CGM.getTriple().isOSBinFormatMachO())
6810 IvarOffsetGV->setSection("__DATA, __objc_ivar
");
6811 return IvarOffsetGV;
6832CGObjCNonFragileABIMac::EmitIvarList(const ObjCImplementationDecl *ID) {
6834 ConstantInitBuilder builder(CGM);
6835 auto ivarList = builder.beginStruct();
6836 ivarList.addInt(ObjCTypes.IntTy,
6837 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy));
6838 auto ivarCountSlot = ivarList.addPlaceholder();
6839 auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy);
6841 const ObjCInterfaceDecl *OID = ID->getClassInterface();
6842 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface
");
6844 // FIXME. Consolidate this with similar code in GenerateClass.
6846 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin(); IVD;
6847 IVD = IVD->getNextIvar()) {
6848 // Ignore unnamed bit-fields.
6849 if (!IVD->getDeclName())
6852 auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy);
6853 ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD,
6854 ComputeIvarBaseOffset(CGM, ID, IVD)));
6855 ivar.add(GetMethodVarName(IVD->getIdentifier()));
6856 ivar.add(GetMethodVarType(IVD));
6857 llvm::Type *FieldTy = CGM.getTypes().ConvertTypeForMem(IVD->getType());
6858 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
6860 CGM.getContext().getPreferredTypeAlign(IVD->getType().getTypePtr()) >>
6862 Align = llvm::Log2_32(Align);
6863 ivar.addInt(ObjCTypes.IntTy, Align);
6864 // NOTE. Size of a bitfield does not match gcc's, because of the
6865 // way bitfields are treated special in each. But I am told that
6866 // 'size' for bitfield ivars is ignored by the runtime so it does
6867 // not matter. If it matters, there is enough info to get the
6869 ivar.addInt(ObjCTypes.IntTy, Size);
6870 ivar.finishAndAddTo(ivars);
6872 // Return null for empty list.
6873 if (ivars.empty()) {
6876 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
6879 auto ivarCount = ivars.size();
6880 ivars.finishAndAddTo(ivarList);
6881 ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount);
6883 const char *Prefix = "_OBJC_$_INSTANCE_VARIABLES_
";
6884 llvm::GlobalVariable *GV = finishAndCreateGlobal(
6885 ivarList, Prefix + OID->getObjCRuntimeNameAsString(), CGM);
6886 CGM.addCompilerUsedGlobal(GV);
6891CGObjCNonFragileABIMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
6892 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
6894 assert(!PD->isNonRuntimeProtocol() &&
6895 "attempting to GetOrEmit a non-runtime protocol
");
6897 // We use the initializer as a marker of whether this is a forward
6898 // reference or not. At module finalization we add the empty
6899 // contents for protocols which were referenced but never defined.
6900 llvm::SmallString<64> Protocol;
6901 llvm::raw_svector_ostream(Protocol)
6902 << "_OBJC_PROTOCOL_$_
" << PD->getObjCRuntimeNameAsString();
6904 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
6905 false, llvm::GlobalValue::ExternalLinkage,
6907 if (!CGM.getTriple().isOSBinFormatMachO())
6908 Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol));
6935CGObjCNonFragileABIMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
6936 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
6938 // Early exit if a defining object has already been generated.
6939 if (Entry && Entry->hasInitializer())
6942 // Use the protocol definition, if there is one.
6943 assert(PD->hasDefinition() &&
6944 "emitting protocol metadata without definition
");
6945 PD = PD->getDefinition();
6947 auto methodLists = ProtocolMethodLists::get(PD);
6949 ConstantInitBuilder builder(CGM);
6950 auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy);
6953 values.addNullPointer(ObjCTypes.ObjectPtrTy);
6954 values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
6955 values.add(EmitProtocolList("_OBJC_$_PROTOCOL_REFS_
" +
6956 PD->getObjCRuntimeNameAsString(),
6957 PD->protocol_begin(), PD->protocol_end()));
6958 values.add(methodLists.emitMethodList(
6959 this, PD, ProtocolMethodLists::RequiredInstanceMethods));
6960 values.add(methodLists.emitMethodList(
6961 this, PD, ProtocolMethodLists::RequiredClassMethods));
6962 values.add(methodLists.emitMethodList(
6963 this, PD, ProtocolMethodLists::OptionalInstanceMethods));
6964 values.add(methodLists.emitMethodList(
6965 this, PD, ProtocolMethodLists::OptionalClassMethods));
6967 EmitPropertyList("_OBJC_$_PROP_LIST_
" + PD->getObjCRuntimeNameAsString(),
6968 nullptr, PD, ObjCTypes, false));
6970 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
6971 values.addInt(ObjCTypes.IntTy, Size);
6972 values.addInt(ObjCTypes.IntTy, 0);
6973 values.add(EmitProtocolMethodTypes(
6974 "_OBJC_$_PROTOCOL_METHOD_TYPES_
" + PD->getObjCRuntimeNameAsString(),
6975 methodLists.emitExtendedTypesArray(this), ObjCTypes));
6977 // const char *demangledName;
6978 values.addNullPointer(ObjCTypes.Int8PtrTy);
6980 values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_
" +
6981 PD->getObjCRuntimeNameAsString(),
6982 nullptr, PD, ObjCTypes, true));
6985 // Already created, fix the linkage and update the initializer.
6986 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
6987 values.finishAndSetAsInitializer(Entry);
6989 llvm::SmallString<64> symbolName;
6990 llvm::raw_svector_ostream(symbolName)
6991 << "_OBJC_PROTOCOL_$_
" << PD->getObjCRuntimeNameAsString();
6993 Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(),
6995 llvm::GlobalValue::WeakAnyLinkage);
6996 if (!CGM.getTriple().isOSBinFormatMachO())
6997 Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName));
6999 Protocols[PD->getIdentifier()] = Entry;
7001 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
7002 CGM.addUsedGlobal(Entry);
7004 // Use this protocol meta-data to build protocol list table in section
7005 // __DATA, __objc_protolist
7006 llvm::SmallString<64> ProtocolRef;
7007 llvm::raw_svector_ostream(ProtocolRef)
7008 << "_OBJC_LABEL_PROTOCOL_$_
" << PD->getObjCRuntimeNameAsString();
7010 llvm::GlobalVariable *PTGV = new llvm::GlobalVariable(
7011 CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy, false,
7012 llvm::GlobalValue::WeakAnyLinkage, Entry, ProtocolRef);
7013 if (!CGM.getTriple().isOSBinFormatMachO())
7014 PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef));
7016 CGM.getDataLayout().getABITypeAlign(ObjCTypes.ProtocolnfABIPtrTy));
7018 GetSectionName("__objc_protolist
", "coalesced,no_dead_strip
"));
7019 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
7020 CGM.addUsedGlobal(PTGV);
7032llvm::Constant *CGObjCNonFragileABIMac::EmitProtocolList(
7033 Twine Name, ObjCProtocolDecl::protocol_iterator begin,
7034 ObjCProtocolDecl::protocol_iterator end) {
7035 // Just return null for empty protocol lists
7036 auto Protocols = GetRuntimeProtocolList(begin, end);
7037 if (Protocols.empty())
7038 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
7040 SmallVector<llvm::Constant *, 16> ProtocolRefs;
7041 ProtocolRefs.reserve(Protocols.size());
7043 for (const auto *PD : Protocols)
7044 ProtocolRefs.push_back(GetProtocolRef(PD));
7046 // If all of the protocols in the protocol list are objc_non_runtime_protocol
7048 if (ProtocolRefs.size() == 0)
7049 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
7051 // FIXME: We shouldn't need to do this lookup here, should we?
7052 SmallString<256> TmpName;
7053 Name.toVector(TmpName);
7054 llvm::GlobalVariable *GV =
7055 CGM.getModule().getGlobalVariable(TmpName.str(), true);
7059 ConstantInitBuilder builder(CGM);
7060 auto values = builder.beginStruct();
7061 auto countSlot = values.addPlaceholder();
7063 // A null-terminated array of protocols.
7064 auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy);
7065 for (auto const &proto : ProtocolRefs)
7067 auto count = array.size();
7068 array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy);
7070 array.finishAndAddTo(values);
7071 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
7073 GV = finishAndCreateGlobal(values, Name, CGM);
7074 CGM.addCompilerUsedGlobal(GV);
7084LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
7085 CodeGen::CodeGenFunction &CGF, QualType ObjectTy, llvm::Value *BaseValue,
7086 const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) {
7087 ObjCInterfaceDecl *ID = ObjectTy->castAs<ObjCObjectType>()->getInterface();
7088 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
7089 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
7094CGObjCNonFragileABIMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
7095 const ObjCInterfaceDecl *Interface,
7096 const ObjCIvarDecl *Ivar) {
7097 llvm::Value *IvarOffsetValue;
7098 if (isClassLayoutKnownStatically(Interface)) {
7099 IvarOffsetValue = llvm::ConstantInt::get(
7100 ObjCTypes.IvarOffsetVarTy,
7101 ComputeIvarBaseOffset(CGM, Interface->getImplementation(), Ivar));
7103 llvm::GlobalVariable *GV = ObjCIvarOffsetVariable(Interface, Ivar);
7104 IvarOffsetValue = CGF.Builder.CreateAlignedLoad(GV->getValueType(), GV,
7105 CGF.getSizeAlign(), "ivar
");
7106 if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
7107 cast<llvm::LoadInst>(IvarOffsetValue)
7108 ->setMetadata(llvm::LLVMContext::MD_invariant_load,
7109 llvm::MDNode::get(VMContext, {}));
7112 // This could be 32bit int or 64bit integer depending on the architecture.
7113 // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
7114 // as this is what caller always expects.
7115 if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
7116 IvarOffsetValue = CGF.Builder.CreateIntCast(
7117 IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv
");
7118 return IvarOffsetValue;
7121static void appendSelectorForMessageRefTable(std::string &buffer,
7122 Selector selector) {
7123 if (selector.isUnarySelector()) {
7124 buffer += selector.getNameForSlot(0);
7128 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
7129 buffer += selector.getNameForSlot(i);
7144RValue CGObjCNonFragileABIMac::EmitVTableMessageSend(
7145 CodeGenFunction &CGF, ReturnValueSlot returnSlot, QualType resultType,
7146 Selector selector, llvm::Value *arg0, QualType arg0Type, bool isSuper,
7147 const CallArgList &formalArgs, const ObjCMethodDecl *method) {
7148 // Compute the actual arguments.
7151 // First argument: the receiver / super-call structure.
7153 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
7154 args.add(RValue::get(arg0), arg0Type);
7156 // Second argument: a pointer to the message ref structure. Leave
7157 // the actual argument value blank for now.
7158 args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy);
7160 llvm::append_range(args, formalArgs);
7162 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
7164 NullReturnState nullReturn;
7166 // Find the function to call and the mangled name for the message
7167 // ref structure. Using a different mangled name wouldn't actually
7168 // be a problem; it would just be a waste.
7170 // The runtime currently never uses vtable dispatch for anything
7171 // except normal, non-super message-sends.
7172 // FIXME: don't use this for that.
7173 llvm::FunctionCallee fn = nullptr;
7174 std::string messageRefName("_
");
7175 if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
7177 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
7178 messageRefName += "objc_msgSendSuper2_stret_fixup
";
7180 nullReturn.init(CGF, arg0);
7181 fn = ObjCTypes.getMessageSendStretFixupFn();
7182 messageRefName += "objc_msgSend_stret_fixup
";
7184 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
7185 fn = ObjCTypes.getMessageSendFpretFixupFn();
7186 messageRefName += "objc_msgSend_fpret_fixup
";
7189 fn = ObjCTypes.getMessageSendSuper2FixupFn();
7190 messageRefName += "objc_msgSendSuper2_fixup
";
7192 fn = ObjCTypes.getMessageSendFixupFn();
7193 messageRefName += "objc_msgSend_fixup
";
7196 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend
");
7197 messageRefName += '_';
7199 // Append the selector name, except use underscores anywhere we
7200 // would have used colons.
7201 appendSelectorForMessageRefTable(messageRefName, selector);
7203 llvm::GlobalVariable *messageRef =
7204 CGM.getModule().getGlobalVariable(messageRefName);
7206 // Build the message ref structure.
7207 ConstantInitBuilder builder(CGM);
7208 auto values = builder.beginStruct();
7209 values.add(cast<llvm::Constant>(fn.getCallee()));
7210 values.add(GetMethodVarName(selector));
7211 messageRef = values.finishAndCreateGlobal(
7212 messageRefName, CharUnits::fromQuantity(16),
7213 /*constant*/ false, llvm::GlobalValue::WeakAnyLinkage);
7214 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
7215 messageRef->setSection(GetSectionName("__objc_msgrefs
", "coalesced
"));
7218 bool requiresnullCheck = false;
7219 if (CGM.getLangOpts().ObjCAutoRefCount && method)
7220 for (const auto *ParamDecl : method->parameters()) {
7221 if (ParamDecl->isDestroyedInCallee()) {
7222 if (!nullReturn.NullBB)
7223 nullReturn.init(CGF, arg0);
7224 requiresnullCheck = true;
7230 Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy),
7231 ObjCTypes.MessageRefTy, CGF.getPointerAlign());
7233 // Update the message ref argument.
7234 args[1].setRValue(RValue::get(mref, CGF));
7236 // Load the function to call from the message ref table.
7237 Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0);
7238 llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn
");
7240 calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType);
7241 CGCallee callee(CGCalleeInfo(), calleePtr);
7243 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
7244 return nullReturn.complete(CGF, returnSlot, result, resultType, formalArgs,
7245 requiresnullCheck ? method : nullptr);
7249CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSend(
7250 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
7251 Selector Sel, llvm::Value *Receiver, const CallArgList &CallArgs,
7252 const ObjCInterfaceDecl *Class, const ObjCMethodDecl *Method) {
7253 return isVTableDispatchedSelector(Sel)
7254 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel, Receiver,
7255 CGF.getContext().getObjCIdType(), false,
7257 : EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
7258 CGF.getContext().getObjCIdType(), false,
7259 CallArgs, Method, Class, ObjCTypes);
7263CGObjCNonFragileABIMac::GetClassGlobal(const ObjCInterfaceDecl *ID,
7265 ForDefinition_t isForDefinition) {
7267 (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix());
7268 return GetClassGlobal((prefix + ID->getObjCRuntimeNameAsString()).str(),
7269 isForDefinition, ID->isWeakImported(),
7271 CGM.getTriple().isOSBinFormatCOFF() &&
7272 ID->hasAttr<DLLImportAttr>());
7276CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name,
7277 ForDefinition_t IsForDefinition,
7278 bool Weak, bool DLLImport) {
7279 llvm::GlobalValue::LinkageTypes L =
7280 Weak ? llvm::GlobalValue::ExternalWeakLinkage
7281 : llvm::GlobalValue::ExternalLinkage;
7283 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
7284 if (!GV || GV->getValueType() != ObjCTypes.ClassnfABITy) {
7285 auto *NewGV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false, L,
7289 NewGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
7292 GV->replaceAllUsesWith(NewGV);
7293 GV->eraseFromParent();
7296 CGM.getModule().insertGlobalVariable(GV);
7299 assert(GV->getLinkage() == L);
7304CGObjCNonFragileABIMac::GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID) {
7305 llvm::Constant *ClassGV =
7306 GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
7308 if (!ID->hasAttr<ObjCClassStubAttr>())
7311 ClassGV = llvm::ConstantExpr::getPointerCast(ClassGV, ObjCTypes.Int8PtrTy);
7313 // Stub classes are pointer-aligned. Classrefs pointing at stub classes
7314 // must set the least significant bit set to 1.
7315 auto *Idx = llvm::ConstantInt::get(CGM.Int32Ty, 1);
7316 return llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, ClassGV, Idx);
7320CGObjCNonFragileABIMac::EmitLoadOfClassRef(CodeGenFunction &CGF,
7321 const ObjCInterfaceDecl *ID,
7322 llvm::GlobalVariable *Entry) {
7323 if (ID && ID->hasAttr<ObjCClassStubAttr>()) {
7324 // Classrefs pointing at Objective-C stub classes must be loaded by calling
7325 // a special runtime function.
7326 return CGF.EmitRuntimeCall(ObjCTypes.getLoadClassrefFn(), Entry,
7327 "load_classref_result
");
7330 CharUnits Align = CGF.getPointerAlign();
7331 return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry, Align);
7334llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(
7335 CodeGenFunction &CGF, IdentifierInfo *II, const ObjCInterfaceDecl *ID) {
7336 llvm::GlobalVariable *&Entry = ClassReferences[II];
7339 llvm::Constant *ClassGV;
7341 ClassGV = GetClassGlobalForClassRef(ID);
7343 ClassGV = GetClassGlobal((getClassSymbolPrefix() + II->getName()).str(),
7345 assert(ClassGV->getType() == ObjCTypes.ClassnfABIPtrTy &&
7346 "classref was emitted with the wrong
type?
");
7349 std::string SectionName =
7350 GetSectionName("__objc_classrefs
", "regular,no_dead_strip
");
7351 Entry = new llvm::GlobalVariable(
7352 CGM.getModule(), ClassGV->getType(), false,
7353 getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV,
7354 "OBJC_CLASSLIST_REFERENCES_$_
");
7355 Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
7356 if (!ID || !ID->hasAttr<ObjCClassStubAttr>())
7357 Entry->setSection(SectionName);
7359 CGM.addCompilerUsedGlobal(Entry);
7362 return EmitLoadOfClassRef(CGF, ID, Entry);
7365llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
7366 const ObjCInterfaceDecl *ID) {
7367 // If the class has the objc_runtime_visible attribute, we need to
7368 // use the Objective-C runtime to get the class.
7369 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
7370 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
7372 return EmitClassRefFromId(CGF, ID->getIdentifier(), ID);
7376CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
7377 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool
");
7378 return EmitClassRefFromId(CGF, II, nullptr);
7382CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
7383 const ObjCInterfaceDecl *ID) {
7384 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
7387 llvm::Constant *ClassGV = GetClassGlobalForClassRef(ID);
7388 std::string SectionName =
7389 GetSectionName("__objc_superrefs
", "regular,no_dead_strip
");
7390 Entry = new llvm::GlobalVariable(CGM.getModule(), ClassGV->getType(), false,
7391 llvm::GlobalValue::PrivateLinkage, ClassGV,
7392 "OBJC_CLASSLIST_SUP_REFS_$_
");
7393 Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
7394 Entry->setSection(SectionName);
7395 CGM.addCompilerUsedGlobal(Entry);
7398 return EmitLoadOfClassRef(CGF, ID, Entry);
7404llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(
7405 CodeGenFunction &CGF, const ObjCInterfaceDecl *ID, bool Weak) {
7406 CharUnits Align = CGF.getPointerAlign();
7407 llvm::GlobalVariable *&Entry = MetaClassReferences[ID->getIdentifier()];
7409 auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition);
7410 std::string SectionName =
7411 GetSectionName("__objc_superrefs
", "regular,no_dead_strip
");
7412 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
7413 false, llvm::GlobalValue::PrivateLinkage,
7414 MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_
");
7415 Entry->setAlignment(Align.getAsAlign());
7416 Entry->setSection(SectionName);
7417 CGM.addCompilerUsedGlobal(Entry);
7420 return CGF.Builder.CreateAlignedLoad(ObjCTypes.ClassnfABIPtrTy, Entry, Align);
7425llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
7426 const ObjCInterfaceDecl *ID) {
7427 if (ID->isWeakImported()) {
7428 auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
7430 assert(!isa<llvm::GlobalVariable>(ClassGV) ||
7431 cast<llvm::GlobalVariable>(ClassGV)->hasExternalWeakLinkage());
7434 return EmitClassRef(CGF, ID);
7440CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSendSuper(
7441 CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
7442 Selector Sel, const ObjCInterfaceDecl *Class, bool isCategoryImpl,
7443 llvm::Value *Receiver, bool IsClassMessage,
7444 const CodeGen::CallArgList &CallArgs, const ObjCMethodDecl *Method) {
7446 // Create and init a super structure; this is a (receiver, class)
7447 // pair we will pass to objc_msgSendSuper.
7448 RawAddress ObjCSuper = CGF.CreateTempAlloca(
7449 ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super
");
7451 llvm::Value *ReceiverAsObject =
7452 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
7453 CGF.Builder.CreateStore(ReceiverAsObject,
7454 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
7456 // If this is a class message the metaclass is passed as the target.
7457 llvm::Value *Target;
7459 Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported());
7461 Target = EmitSuperClassRef(CGF, Class);
7463 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
7465 llvm::Type *ClassTy =
7466 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
7467 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
7468 CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
7470 return (isVTableDispatchedSelector(Sel))
7471 ? EmitVTableMessageSend(
7472 CGF, Return, ResultType, Sel, ObjCSuper.getPointer(),
7473 ObjCTypes.SuperPtrCTy, true, CallArgs, Method)
7474 : EmitMessageSend(CGF, Return, ResultType, Sel,
7475 ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
7476 true, CallArgs, Method, Class, ObjCTypes);
7479llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
7481 Address Addr = EmitSelectorAddr(Sel);
7483 llvm::LoadInst *LI = CGF.Builder.CreateLoad(Addr);
7484 LI->setMetadata(llvm::LLVMContext::MD_invariant_load,
7485 llvm::MDNode::get(VMContext, {}));
7489ConstantAddress CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) {
7490 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
7491 CharUnits Align = CGM.getPointerAlign();
7493 std::string SectionName =
7494 GetSectionName("__objc_selrefs
", "literal_pointers,no_dead_strip
");
7495 Entry = new llvm::GlobalVariable(
7496 CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
7497 getLinkageTypeForObjCMetadata(CGM, SectionName), GetMethodVarName(Sel),
7498 "OBJC_SELECTOR_REFERENCES_
");
7499 Entry->setExternallyInitialized(true);
7500 Entry->setSection(SectionName);
7501 Entry->setAlignment(Align.getAsAlign());
7502 CGM.addCompilerUsedGlobal(Entry);
7505 return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align);
7511void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
7512 llvm::Value *src, Address dst,
7513 llvm::Value *ivarOffset) {
7514 llvm::Type *SrcTy = src->getType();
7515 if (!isa<llvm::PointerType>(SrcTy)) {
7516 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
7517 assert(Size <= 8 && "does
not support size > 8
");
7518 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7519 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
7520 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7522 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7523 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
7524 ObjCTypes.PtrObjectPtrTy);
7525 llvm::Value *args[] = {src, dstVal, ivarOffset};
7526 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
7532void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
7533 CodeGen::CodeGenFunction &CGF, llvm::Value *src, Address dst) {
7534 llvm::Type *SrcTy = src->getType();
7535 if (!isa<llvm::PointerType>(SrcTy)) {
7536 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
7537 assert(Size <= 8 && "does
not support size > 8
");
7538 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7539 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
7540 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7542 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7543 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
7544 ObjCTypes.PtrObjectPtrTy);
7545 llvm::Value *args[] = {src, dstVal};
7546 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args,
7550void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
7551 CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr,
7552 llvm::Value *Size) {
7553 llvm::Value *args[] = {DestPtr.emitRawPointer(CGF),
7554 SrcPtr.emitRawPointer(CGF), Size};
7555 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
7562CGObjCNonFragileABIMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
7563 Address AddrWeakObj) {
7564 llvm::Type *DestTy = AddrWeakObj.getElementType();
7565 llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast(
7566 AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy);
7567 llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall(
7568 ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread
");
7569 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
7576void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
7577 llvm::Value *src, Address dst) {
7578 llvm::Type *SrcTy = src->getType();
7579 if (!isa<llvm::PointerType>(SrcTy)) {
7580 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
7581 assert(Size <= 8 && "does
not support size > 8
");
7582 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7583 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
7584 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7586 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7587 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
7588 ObjCTypes.PtrObjectPtrTy);
7589 llvm::Value *args[] = {src, dstVal};
7590 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args,
7597void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
7598 llvm::Value *src, Address dst,
7600 llvm::Type *SrcTy = src->getType();
7601 if (!isa<llvm::PointerType>(SrcTy)) {
7602 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
7603 assert(Size <= 8 && "does
not support size > 8
");
7604 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
7605 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
7606 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
7608 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
7609 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
7610 ObjCTypes.PtrObjectPtrTy);
7611 llvm::Value *args[] = {src, dstVal};
7613 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), args,
7616 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), args,
7617 "threadlocalassign
");
7620void CGObjCNonFragileABIMac::EmitSynchronizedStmt(
7621 CodeGen::CodeGenFunction &CGF, const ObjCAtSynchronizedStmt &S) {
7622 EmitAtSynchronizedStmt(CGF, S, ObjCTypes.getSyncEnterFn(),
7623 ObjCTypes.getSyncExitFn());
7626llvm::Constant *CGObjCNonFragileABIMac::GetEHType(QualType T) {
7627 // There's a particular fixed type info for 'id'.
7628 if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
7629 auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id
");
7631 IDEHType = new llvm::GlobalVariable(
7632 CGM.getModule(), ObjCTypes.EHTypeTy, false,
7633 llvm::GlobalValue::ExternalLinkage, nullptr, "OBJC_EHTYPE_id
");
7634 if (CGM.getTriple().isOSBinFormatCOFF())
7635 IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id
"));
7640 // All other types should be Objective-C interface pointer types.
7641 const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
7644 const ObjCInterfaceType *IT = PT->getInterfaceType();
7645 assert(IT && "Invalid
@catch type.
");
7647 return GetInterfaceEHType(IT->getDecl(), NotForDefinition);
7650void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
7651 const ObjCAtTryStmt &S) {
7652 EmitTryCatchStmt(CGF, S, ObjCTypes.getObjCBeginCatchFn(),
7653 ObjCTypes.getObjCEndCatchFn(),
7654 ObjCTypes.getExceptionRethrowFn());
7658void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
7659 const ObjCAtThrowStmt &S,
7660 bool ClearInsertionPoint) {
7661 if (const Expr *ThrowExpr = S.getThrowExpr()) {
7662 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
7663 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
7664 llvm::CallBase *Call =
7665 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception);
7666 Call->setDoesNotReturn();
7668 llvm::CallBase *Call =
7669 CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn());
7670 Call->setDoesNotReturn();
7673 CGF.Builder.CreateUnreachable();
7674 if (ClearInsertionPoint)
7675 CGF.Builder.ClearInsertionPoint();
7679CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
7680 ForDefinition_t IsForDefinition) {
7681 llvm::GlobalVariable *&Entry = EHTypeReferences[ID->getIdentifier()];
7682 StringRef ClassName = ID->getObjCRuntimeNameAsString();
7684 // If we don't need a definition, return the entry if found or check
7685 // if we use an external reference.
7686 if (!IsForDefinition) {
7690 // If this type (or a super class) has the __objc_exception__
7691 // attribute, emit an external reference.
7692 if (hasObjCExceptionAttribute(CGM.getContext(), ID)) {
7693 std::string EHTypeName = ("OBJC_EHTYPE_$_
" + ClassName).str();
7694 Entry = new llvm::GlobalVariable(
7695 CGM.getModule(), ObjCTypes.EHTypeTy, false,
7696 llvm::GlobalValue::ExternalLinkage, nullptr, EHTypeName);
7697 CGM.setGVProperties(Entry, ID);
7702 // Otherwise we need to either make a new entry or fill in the initializer.
7703 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition
");
7705 std::string VTableName = "objc_ehtype_vtable
";
7706 auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName);
7708 VTableGV = new llvm::GlobalVariable(
7709 CGM.getModule(), ObjCTypes.Int8PtrTy, false,
7710 llvm::GlobalValue::ExternalLinkage, nullptr, VTableName);
7711 if (CGM.getTriple().isOSBinFormatCOFF())
7712 VTableGV->setDLLStorageClass(getStorage(CGM, VTableName));
7715 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
7716 llvm::Constant *VTablePtr = llvm::ConstantExpr::getInBoundsGetElementPtr(
7717 VTableGV->getValueType(), VTableGV, VTableIdx);
7719 ConstantInitBuilder builder(CGM);
7720 auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
7721 const PointerAuthSchema &TypeInfoSchema =
7722 CGM.getCodeGenOpts().PointerAuth.CXXTypeInfoVTablePointer;
7723 values.addSignedPointer(VTablePtr, TypeInfoSchema, GlobalDecl(), QualType());
7725 values.add(GetClassName(ClassName));
7726 values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition));
7728 llvm::GlobalValue::LinkageTypes L = IsForDefinition
7729 ? llvm::GlobalValue::ExternalLinkage
7730 : llvm::GlobalValue::WeakAnyLinkage;
7732 values.finishAndSetAsInitializer(Entry);
7733 Entry->setAlignment(CGM.getPointerAlign().getAsAlign());
7735 Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_
" + ClassName,
7736 CGM.getPointerAlign(),
7737 /*constant*/ false, L);
7738 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
7739 CGM.setGVProperties(Entry, ID);
7741 assert(Entry->getLinkage() == L);
7743 if (!CGM.getTriple().isOSBinFormatCOFF())
7744 if (ID->getVisibility() == HiddenVisibility)
7745 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
7747 if (IsForDefinition)
7748 if (CGM.getTriple().isOSBinFormatMachO())
7749 Entry->setSection("__DATA,__objc_const
");
7756CodeGen::CGObjCRuntime *
7757CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
7758 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7759 case ObjCRuntime::FragileMacOSX:
7760 return new CGObjCMac(CGM);
7762 case ObjCRuntime::MacOSX:
7763 case ObjCRuntime::iOS:
7764 case ObjCRuntime::WatchOS:
7765 return new CGObjCNonFragileABIMac(CGM);
7767 case ObjCRuntime::GNUstep:
7768 case ObjCRuntime::GCC:
7769 case ObjCRuntime::ObjFW:
7770 llvm_unreachable("these runtimes are
not Mac runtimes
");
7772 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)
@ kCFTaggedObjectID_Integer
static void addIfPresent(llvm::DenseSet< llvm::Value * > &S, Address V)
static void PushProtocolProperties(llvm::SmallPtrSet< const IdentifierInfo *, 16 > &PropertySet, SmallVectorImpl< const ObjCPropertyDecl * > &Properties, const ObjCProtocolDecl *Proto, bool IsClassProperty)
static llvm::GlobalVariable * finishAndCreateGlobal(ConstantInitBuilder::StructBuilder &Builder, const llvm::Twine &Name, CodeGenModule &CGM)
A helper function to create an internal or private global variable.
static bool hasMRCWeakIvars(CodeGenModule &CGM, const ObjCImplementationDecl *ID)
For compatibility, we only want to set the "HasMRCWeakIvars" flag (and actually fill in a layout stri...
@ NonFragileABI_Class_HasCXXDestructorOnly
Class has non-trivial destructors, but zero-initialization is okay.
@ NonFragileABI_Class_Hidden
Has hidden visibility.
@ NonFragileABI_Class_HasCXXStructors
Has a non-trivial constructor or destructor.
@ NonFragileABI_Class_Exception
Has the exception attribute.
@ NonFragileABI_Class_HasIvarReleaser
(Obsolete) ARC-specific: this class has a .release_ivars method
@ NonFragileABI_Class_Root
Is a root class.
@ NonFragileABI_Class_Meta
Is a meta-class.
@ NonFragileABI_Class_HasMRCWeakIvars
Class implementation was compiled under MRC and has MRC weak ivars.
@ NonFragileABI_Class_CompiledByARC
Class implementation was compiled under ARC.
static llvm::Constant * getConstantGEP(llvm::LLVMContext &VMContext, llvm::GlobalVariable *C, unsigned idx0, unsigned idx1)
getConstantGEP() - Help routine to construct simple GEPs.
static bool hasObjCExceptionAttribute(ASTContext &Context, const ObjCInterfaceDecl *OID)
hasObjCExceptionAttribute - Return true if this class or any super class has the objc_exception attri...
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
Defines the clang::LangOptions interface.
llvm::MachO::Target Target
Defines the Objective-C statement AST node classes.
__device__ __2f16 float __ockl_bool s
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
CanQualType getCanonicalParamType(QualType T) const
Return the canonical parameter type corresponding to the specific potentially non-canonical one.
QualType getObjCClassType() const
Represents the Objective-C Class type.
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const LangOptions & getLangOpts() const
SelectorTable & Selectors
CanQualType getCanonicalSizeType() const
const ASTRecordLayout & getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const
Get or compute information about the layout of the specified Objective-C interface.
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
QualType getObjCSelType() const
Retrieve the type that corresponds to the predefined Objective-C 'SEL' type.
QualType getObjCIdType() const
Represents the Objective-CC id type.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
QualType getObjCClassRedefinitionType() const
Retrieve the type that Class has been defined to, which may be different from the built-in Class if C...
QualType getObjCIdRedefinitionType() const
Retrieve the type that id has been defined to, which may be different from the built-in id if id has ...
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
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.
PointerAuthOptions PointerAuth
Configuration for pointer-signing.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
llvm::Type * getElementType() const
Return the type of the values stored in this address.
unsigned getIndex() const
CharUnits getOffset() const
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.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
llvm::Type * ConvertType(QualType T)
void EmitAutoVarDecl(const VarDecl &D)
EmitAutoVarDecl - Emit an auto variable declaration.
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
llvm::Value * EmitObjCThrowOperand(const Expr *expr)
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
JumpDest ReturnBlock
ReturnBlock - Unified return block.
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)
CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
RawAddress getNormalCleanupDestSlot()
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
RawAddress NormalCleanupDest
i32s containing the indexes of the cleanup destinations.
SmallVector< llvm::Value *, 8 > ObjCEHValueStack
ObjCEHValueStack - Stack of Objective-C exception values, used for rethrows.
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
llvm::Value * EmitFromMemory(llvm::Value *Value, QualType Ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
llvm::LLVMContext & getLLVMContext()
void PopCleanupBlock(bool FallThroughIsBranchThrough=false, bool ForDeactivation=false)
PopCleanupBlock - Will pop the cleanup entry on the stack and process all branch fixups.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
This class organizes the cross-function state that is used while generating LLVM code.
llvm::Module & getModule() const
llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)
Create or return a runtime function declaration with the specified type and name.
void addCompilerUsedGlobal(llvm::GlobalValue *GV)
Add a global to a list to be added to the llvm.compiler.used metadata.
llvm::Constant * GetAddrOfRTTIDescriptor(QualType Ty, bool ForEH=false)
Get the address of the RTTI descriptor for the given type.
bool ReturnTypeUsesFPRet(QualType ResultType)
Return true iff the given type uses 'fpret' when used as a return type.
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const TargetInfo & getTarget() const
const llvm::DataLayout & getDataLayout() const
bool ReturnTypeUsesFP2Ret(QualType ResultType)
Return true iff the given type uses 'fp2ret' when used as a return type.
const llvm::Triple & getTriple() const
bool ReturnSlotInterferesWithArgs(const CGFunctionInfo &FI)
Return true iff the given type uses an argument slot when 'sret' is used as a return type.
llvm::Constant * CreateRuntimeVariable(llvm::Type *Ty, StringRef Name)
Create a new runtime global variable with the specified type and name.
ConstantAddress GetAddrOfConstantCFString(const StringLiteral *Literal)
Return a pointer to a constant CFString object for the given string.
ASTContext & getContext() const
bool ReturnTypeUsesSRet(const CGFunctionInfo &FI)
Return true iff the given type uses 'sret' when used as a return type.
const CodeGenOptions & getCodeGenOpts() const
llvm::LLVMContext & getLLVMContext()
llvm::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
ConstantAddress GetAddrOfConstantCString(const std::string &Str, 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
Computes the bit width of this field, if this is a bit field.
GlobalDecl - represents a global declaration.
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
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
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
RecordDecl * getDefinitionOrSelf() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getOriginalDecl() 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
bool isObjCQualifiedIdType() const
bool isObjCIdType() const
bool isObjCObjectPointerType() const
bool isObjCQualifiedClassType() const
bool isObjCClassType() const
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
const T * castAsCanonical() const
Return this type's canonical type cast to the specified type.
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
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.
The JSON file list parser is used to communicate input to InstallAPI.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
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.
CLINKAGE int printf(__constant const char *st,...) __attribute__((format(printf
float __ovld __cnfn length(float)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
llvm::BasicBlock * getBlock() const
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
PointerAuthSchema ObjCIsaPointers
The ABI for Objective-C isa pointers.