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(llvm::FunctionType::get(CGM.VoidTy,
83 "objc_msgSend_stret");
91 llvm::FunctionCallee getMessageSendFpretFn()
const {
92 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
93 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy,
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(llvm::FunctionType::get(resultType,
111 "objc_msgSend_fp2ret");
119 llvm::FunctionCallee getMessageSendSuperFn()
const {
120 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
121 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
123 "objc_msgSendSuper");
130 llvm::FunctionCallee getMessageSendSuperFn2()
const {
131 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
132 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
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;
190 llvm::Type *ExternalProtocolPtrTy;
193 llvm::Type *getExternalProtocolPtrTy() {
194 if (!ExternalProtocolPtrTy) {
200 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(
T);
203 return ExternalProtocolPtrTy;
212 llvm::StructType *SuperTy;
214 llvm::PointerType *SuperPtrTy;
218 llvm::StructType *PropertyTy;
222 llvm::StructType *PropertyListTy;
224 llvm::PointerType *PropertyListPtrTy;
227 llvm::StructType *MethodTy;
232 llvm::PointerType *CachePtrTy;
234 llvm::FunctionCallee getGetPropertyFn() {
243 llvm::FunctionType *FTy =
244 Types.GetFunctionType(
245 Types.arrangeBuiltinFunctionDeclaration(IdType, Params));
249 llvm::FunctionCallee getSetPropertyFn() {
262 llvm::FunctionType *FTy =
263 Types.GetFunctionType(
264 Types.arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Params));
268 llvm::FunctionCallee getOptimizedSetPropertyFn(
bool atomic,
bool copy) {
283 Params.push_back(IdType);
284 Params.push_back(SelType);
285 Params.push_back(IdType);
287 llvm::FunctionType *FTy =
288 Types.GetFunctionType(
289 Types.arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Params));
292 name =
"objc_setProperty_atomic_copy";
293 else if (atomic && !copy)
294 name =
"objc_setProperty_atomic";
295 else if (!atomic && copy)
296 name =
"objc_setProperty_nonatomic_copy";
298 name =
"objc_setProperty_nonatomic";
303 llvm::FunctionCallee getCopyStructFn() {
311 Params.push_back(Ctx.
BoolTy);
312 Params.push_back(Ctx.
BoolTy);
313 llvm::FunctionType *FTy =
314 Types.GetFunctionType(
315 Types.arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Params));
323 llvm::FunctionCallee getCppAtomicObjectFunction() {
331 llvm::FunctionType *FTy =
332 Types.GetFunctionType(
333 Types.arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Params));
337 llvm::FunctionCallee getEnumerationMutationFn() {
343 llvm::FunctionType *FTy =
344 Types.GetFunctionType(
345 Types.arrangeBuiltinFunctionDeclaration(Ctx.
VoidTy, Params));
349 llvm::FunctionCallee getLookUpClassFn() {
356 llvm::FunctionType *FTy =
357 Types.GetFunctionType(Types.arrangeBuiltinFunctionDeclaration(
364 llvm::FunctionCallee getGcReadWeakFn() {
367 llvm::FunctionType *FTy =
368 llvm::FunctionType::get(ObjectPtrTy, args,
false);
373 llvm::FunctionCallee getGcAssignWeakFn() {
375 llvm::Type *args[] = {ObjectPtrTy, CGM.
UnqualPtrTy};
376 llvm::FunctionType *FTy =
377 llvm::FunctionType::get(ObjectPtrTy, args,
false);
382 llvm::FunctionCallee getGcAssignGlobalFn() {
384 llvm::Type *args[] = {ObjectPtrTy, CGM.
UnqualPtrTy};
385 llvm::FunctionType *FTy =
386 llvm::FunctionType::get(ObjectPtrTy, args,
false);
391 llvm::FunctionCallee getGcAssignThreadLocalFn() {
393 llvm::Type *args[] = {ObjectPtrTy, CGM.
UnqualPtrTy};
394 llvm::FunctionType *FTy =
395 llvm::FunctionType::get(ObjectPtrTy, args,
false);
400 llvm::FunctionCallee getGcAssignIvarFn() {
403 llvm::FunctionType *FTy =
404 llvm::FunctionType::get(ObjectPtrTy, args,
false);
409 llvm::FunctionCallee GcMemmoveCollectableFn() {
411 llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
412 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args,
false);
417 llvm::FunctionCallee getGcAssignStrongCastFn() {
419 llvm::Type *args[] = {ObjectPtrTy, CGM.
UnqualPtrTy};
420 llvm::FunctionType *FTy =
421 llvm::FunctionType::get(ObjectPtrTy, args,
false);
426 llvm::FunctionCallee getExceptionThrowFn() {
428 llvm::Type *args[] = { ObjectPtrTy };
429 llvm::FunctionType *FTy =
430 llvm::FunctionType::get(CGM.
VoidTy, args,
false);
435 llvm::FunctionCallee getExceptionRethrowFn() {
437 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.
VoidTy,
false);
442 llvm::FunctionCallee getSyncEnterFn() {
444 llvm::Type *args[] = { ObjectPtrTy };
445 llvm::FunctionType *FTy =
446 llvm::FunctionType::get(CGM.
IntTy, args,
false);
451 llvm::FunctionCallee getSyncExitFn() {
453 llvm::Type *args[] = { ObjectPtrTy };
454 llvm::FunctionType *FTy =
455 llvm::FunctionType::get(CGM.
IntTy, args,
false);
459 llvm::FunctionCallee getSendFn(
bool IsSuper)
const {
460 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
463 llvm::FunctionCallee getSendFn2(
bool IsSuper)
const {
464 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
467 llvm::FunctionCallee getSendStretFn(
bool IsSuper)
const {
468 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
471 llvm::FunctionCallee getSendStretFn2(
bool IsSuper)
const {
472 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
475 llvm::FunctionCallee getSendFpretFn(
bool IsSuper)
const {
476 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
479 llvm::FunctionCallee getSendFpretFn2(
bool IsSuper)
const {
480 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
483 llvm::FunctionCallee getSendFp2retFn(
bool IsSuper)
const {
484 return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
487 llvm::FunctionCallee getSendFp2RetFn2(
bool IsSuper)
const {
488 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
496class ObjCTypesHelper :
public ObjCCommonTypesHelper {
499 llvm::StructType *SymtabTy;
501 llvm::PointerType *SymtabPtrTy;
503 llvm::StructType *ModuleTy;
506 llvm::StructType *ProtocolTy;
508 llvm::PointerType *ProtocolPtrTy;
511 llvm::StructType *ProtocolExtensionTy;
514 llvm::PointerType *ProtocolExtensionPtrTy;
517 llvm::StructType *MethodDescriptionTy;
520 llvm::StructType *MethodDescriptionListTy;
523 llvm::PointerType *MethodDescriptionListPtrTy;
525 llvm::StructType *ProtocolListTy;
527 llvm::PointerType *ProtocolListPtrTy;
529 llvm::StructType *CategoryTy;
531 llvm::StructType *ClassTy;
533 llvm::PointerType *ClassPtrTy;
535 llvm::StructType *ClassExtensionTy;
537 llvm::PointerType *ClassExtensionPtrTy;
539 llvm::StructType *IvarTy;
541 llvm::StructType *IvarListTy;
543 llvm::PointerType *IvarListPtrTy;
545 llvm::StructType *MethodListTy;
547 llvm::PointerType *MethodListPtrTy;
550 llvm::StructType *ExceptionDataTy;
553 llvm::FunctionCallee getExceptionTryEnterFn() {
556 llvm::FunctionType::get(CGM.
VoidTy, params,
false),
557 "objc_exception_try_enter");
561 llvm::FunctionCallee getExceptionTryExitFn() {
564 llvm::FunctionType::get(CGM.
VoidTy, params,
false),
565 "objc_exception_try_exit");
569 llvm::FunctionCallee getExceptionExtractFn() {
573 "objc_exception_extract");
577 llvm::FunctionCallee getExceptionMatchFn() {
578 llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
580 llvm::FunctionType::get(CGM.
Int32Ty, params,
false),
581 "objc_exception_match");
585 llvm::FunctionCallee getSetJmpFn() {
589 llvm::FunctionType::get(CGM.
Int32Ty, params,
false),
"_setjmp",
591 llvm::AttributeList::FunctionIndex,
592 llvm::Attribute::NonLazyBind));
601class ObjCNonFragileABITypesHelper :
public ObjCCommonTypesHelper {
604 llvm::StructType *MethodListnfABITy;
607 llvm::PointerType *MethodListnfABIPtrTy;
610 llvm::StructType *ProtocolnfABITy;
613 llvm::PointerType *ProtocolnfABIPtrTy;
616 llvm::StructType *ProtocolListnfABITy;
619 llvm::PointerType *ProtocolListnfABIPtrTy;
622 llvm::StructType *ClassnfABITy;
625 llvm::PointerType *ClassnfABIPtrTy;
628 llvm::StructType *IvarnfABITy;
631 llvm::StructType *IvarListnfABITy;
634 llvm::PointerType *IvarListnfABIPtrTy;
637 llvm::StructType *ClassRonfABITy;
640 llvm::PointerType *ImpnfABITy;
643 llvm::StructType *CategorynfABITy;
652 llvm::StructType *MessageRefTy;
657 llvm::Type *MessageRefPtrTy;
666 llvm::StructType *SuperMessageRefTy;
669 llvm::PointerType *SuperMessageRefPtrTy;
671 llvm::FunctionCallee getMessageSendFixupFn() {
673 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
676 "objc_msgSend_fixup");
679 llvm::FunctionCallee getMessageSendFpretFixupFn() {
681 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
684 "objc_msgSend_fpret_fixup");
687 llvm::FunctionCallee getMessageSendStretFixupFn() {
689 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
692 "objc_msgSend_stret_fixup");
695 llvm::FunctionCallee getMessageSendSuper2FixupFn() {
698 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
701 "objc_msgSendSuper2_fixup");
704 llvm::FunctionCallee getMessageSendSuper2StretFixupFn() {
707 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
710 "objc_msgSendSuper2_stret_fixup");
713 llvm::FunctionCallee getObjCEndCatchFn() {
718 llvm::FunctionCallee getObjCBeginCatchFn() {
719 llvm::Type *params[] = { Int8PtrTy };
730 llvm::FunctionCallee getLoadClassrefFn()
const {
736 llvm::Type *params[] = { Int8PtrPtrTy };
738 llvm::AttributeSet AS = llvm::AttributeSet::get(
C, {
739 llvm::Attribute::get(
C, llvm::Attribute::NonLazyBind),
740 llvm::Attribute::getWithMemoryEffects(
C, llvm::MemoryEffects::none()),
741 llvm::Attribute::get(
C, llvm::Attribute::NoUnwind),
744 llvm::FunctionType::get(ClassnfABIPtrTy, params,
false),
747 llvm::AttributeList::FunctionIndex, AS));
748 if (!CGM.
getTriple().isOSBinFormatCOFF())
749 cast<llvm::Function>(F.getCallee())->setLinkage(
750 llvm::Function::ExternalWeakLinkage);
755 llvm::StructType *EHTypeTy;
756 llvm::Type *EHTypePtrTy;
761enum class ObjCLabelType {
774 SKIP_SCAN(
unsigned _skip = 0,
unsigned _scan = 0)
775 : skip(_skip), scan(_scan) {}
782 enum BLOCK_LAYOUT_OPCODE {
789 BLOCK_LAYOUT_OPERATOR = 0,
795 BLOCK_LAYOUT_NON_OBJECT_BYTES = 1,
800 BLOCK_LAYOUT_NON_OBJECT_WORDS = 2,
804 BLOCK_LAYOUT_STRONG = 3,
807 BLOCK_LAYOUT_BYREF = 4,
811 BLOCK_LAYOUT_WEAK = 5,
815 BLOCK_LAYOUT_UNRETAINED = 6
832 enum BLOCK_LAYOUT_OPCODE opcode;
835 RUN_SKIP(
enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
838 : opcode(
Opcode), block_var_bytepos(BytePos), block_var_size(
Size) {}
842 return block_var_bytepos <
b.block_var_bytepos;
847 llvm::LLVMContext &VMContext;
856 llvm::SetVector<IdentifierInfo*> LazySymbols;
862 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
865 llvm::StringMap<llvm::GlobalVariable*> ClassNames;
868 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
875 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
879 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
883 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> DirectMethodDefinitions;
886 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
889 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
892 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
897 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
901 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
923 llvm::WeakTrackingVH ConstantStringClassRef;
926 llvm::StructType *NSConstantStringType =
nullptr;
928 llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap;
932 llvm::Constant *GetMethodVarName(
Selector Sel);
940 bool Extended =
false);
941 llvm::Constant *GetMethodVarType(
const FieldDecl *
D);
949 const Decl *Container);
954 llvm::Constant *GetClassName(StringRef RuntimeName);
968 bool forStrongLayout,
974 return BuildIvarLayout(OI, beginOffset, endOffset,
true,
false);
981 return BuildIvarLayout(OI, beginOffset, endOffset,
false,
hasMRCWeakIvars);
986 void UpdateRunSkipBlockVars(
bool IsByref,
991 void BuildRCBlockVarRecordLayout(
const RecordType *RT,
993 bool ByrefLayout=
false);
995 void BuildRCRecordLayout(
const llvm::StructLayout *RecLayout,
1003 llvm::Constant *getBitmapBlockLayout(
bool ComputeByrefLayout);
1008 const ObjCCommonTypesHelper &ObjCTypes);
1012 llvm::Constant *EmitPropertyList(Twine Name,
1013 const Decl *Container,
1015 const ObjCCommonTypesHelper &ObjCTypes,
1016 bool IsClassProperty);
1020 llvm::Constant *EmitProtocolMethodTypes(Twine Name,
1022 const ObjCCommonTypesHelper &ObjCTypes);
1033 ObjCCommonTypesHelper &ObjCTypes);
1035 std::string GetSectionName(StringRef Section, StringRef MachOAttributes);
1052 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
1056 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
1057 llvm::Constant *
Init,
1061 llvm::GlobalVariable *CreateCStringLiteral(StringRef Name,
1062 ObjCLabelType LabelType,
1063 bool ForceNonFragileABI =
false,
1064 bool NullTerminate =
true);
1077 const ObjCCommonTypesHelper &ObjCTypes);
1081 void EmitImageInfo();
1087 bool isNonFragileABI()
const {
1088 return ObjCABI == 2;
1110 virtual llvm::Constant *GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD)=0;
1112 virtual llvm::Constant *getNSConstantStringClassRef() = 0;
1130enum class MethodListType {
1131 CategoryInstanceMethods,
1132 CategoryClassMethods,
1135 ProtocolInstanceMethods,
1136 ProtocolClassMethods,
1137 OptionalProtocolInstanceMethods,
1138 OptionalProtocolClassMethods,
1143class ProtocolMethodLists {
1146 RequiredInstanceMethods,
1147 RequiredClassMethods,
1148 OptionalInstanceMethods,
1149 OptionalClassMethods
1152 NumProtocolMethodLists = 4
1155 static MethodListType getMethodListKind(Kind kind) {
1157 case RequiredInstanceMethods:
1158 return MethodListType::ProtocolInstanceMethods;
1159 case RequiredClassMethods:
1160 return MethodListType::ProtocolClassMethods;
1161 case OptionalInstanceMethods:
1162 return MethodListType::OptionalProtocolInstanceMethods;
1163 case OptionalClassMethods:
1164 return MethodListType::OptionalProtocolClassMethods;
1166 llvm_unreachable(
"bad kind");
1172 ProtocolMethodLists result;
1174 for (
auto *MD : PD->
methods()) {
1175 size_t index = (2 *
size_t(MD->isOptional()))
1176 + (
size_t(MD->isClassMethod()));
1177 result.Methods[index].push_back(MD);
1183 template <
class Self>
1194 for (
auto &list : Methods) {
1195 for (
auto MD : list) {
1196 result.push_back(self->GetMethodVarType(MD,
true));
1203 template <
class Self>
1207 getMethodListKind(kind), Methods[kind]);
1213class CGObjCMac :
public CGObjCCommonMac {
1215 friend ProtocolMethodLists;
1217 ObjCTypesHelper ObjCTypes;
1221 void EmitModuleInfo();
1225 llvm::Constant *EmitModuleSymbols();
1229 void FinishModule();
1247 llvm::Value *EmitNSAutoreleasePoolClassRef(
CodeGenFunction &CGF)
override;
1268 llvm::Constant *Protocols,
1279 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1299 const ProtocolMethodLists &methodLists);
1303 llvm::Constant *EmitProtocolList(Twine Name,
1315 llvm::Constant *getNSConstantStringClassRef()
override;
1317 llvm::Function *ModuleInitFunction()
override;
1322 Selector Sel, llvm::Value *Receiver,
1331 bool isCategoryImpl, llvm::Value *Receiver,
1346 llvm::Constant *GetEHType(
QualType T)
override;
1357 llvm::FunctionCallee GetPropertyGetFunction()
override;
1358 llvm::FunctionCallee GetPropertySetFunction()
override;
1359 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
1360 bool copy)
override;
1361 llvm::FunctionCallee GetGetStructFunction()
override;
1362 llvm::FunctionCallee GetSetStructFunction()
override;
1363 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override;
1364 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override;
1365 llvm::FunctionCallee EnumerationMutationFunction()
override;
1373 bool ClearInsertionPoint=
true)
override;
1375 Address AddrWeakObj)
override;
1377 llvm::Value *src,
Address dst)
override;
1379 llvm::Value *src,
Address dest,
1380 bool threadlocal =
false)
override;
1382 llvm::Value *src,
Address dest,
1383 llvm::Value *ivarOffset)
override;
1385 llvm::Value *src,
Address dest)
override;
1388 llvm::Value *size)
override;
1392 unsigned CVRQualifiers)
override;
1398class CGObjCNonFragileABIMac :
public CGObjCCommonMac {
1400 friend ProtocolMethodLists;
1401 ObjCNonFragileABITypesHelper ObjCTypes;
1402 llvm::GlobalVariable* ObjCEmptyCacheVar;
1403 llvm::Constant* ObjCEmptyVtableVar;
1406 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
1409 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
1412 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
1416 llvm::DenseSet<Selector> VTableDispatchMethods;
1419 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1423 bool isVTableDispatchedSelector(
Selector Sel);
1427 void FinishNonFragileABIModule();
1432 StringRef SymbolName, StringRef SectionName);
1434 llvm::GlobalVariable * BuildClassRoTInitializer(
unsigned flags,
1435 unsigned InstanceStart,
1436 unsigned InstanceSize,
1440 llvm::Constant *IsAGV,
1441 llvm::Constant *SuperClassGV,
1442 llvm::Constant *ClassRoGV,
1451 llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
1463 unsigned long int offset);
1478 llvm::Constant *EmitProtocolList(Twine Name,
1486 llvm::Value *Receiver,
1494 llvm::Constant *GetClassGlobal(StringRef Name,
1496 bool Weak =
false,
bool DLLImport =
false);
1505 llvm::GlobalVariable *Entry);
1516 llvm::Value *EmitNSAutoreleasePoolClassRef(
CodeGenFunction &CGF)
override;
1531 llvm::GlobalVariable * ObjCIvarOffsetVariable(
1545 StringRef getMetaclassSymbolPrefix()
const {
return "OBJC_METACLASS_$_"; }
1547 StringRef getClassSymbolPrefix()
const {
return "OBJC_CLASS_$_"; }
1550 uint32_t &InstanceStart,
1551 uint32_t &InstanceSize);
1566 bool ImplementationIsNonLazy(
const ObjCImplDecl *OD)
const;
1585 dyn_cast_or_null<ObjCMethodDecl>(CGF.
CurFuncDecl))
1586 if (MD->isInstanceMethod() && !MD->isDirectMethod())
1595 for (;
ID;
ID =
ID->getSuperClass()) {
1598 if (
ID->getIdentifier()->getName() ==
"NSObject")
1603 if (!
ID->getImplementation())
1612 llvm::Constant *getNSConstantStringClassRef()
override;
1614 llvm::Function *ModuleInitFunction()
override;
1619 llvm::Value *Receiver,
1628 bool isCategoryImpl, llvm::Value *Receiver,
1636 {
return EmitSelector(CGF, Sel); }
1638 {
return EmitSelectorAddr(Sel); }
1644 {
return EmitSelector(CGF, Method->
getSelector()); }
1655 llvm::Constant *GetEHType(
QualType T)
override;
1657 llvm::FunctionCallee GetPropertyGetFunction()
override {
1658 return ObjCTypes.getGetPropertyFn();
1660 llvm::FunctionCallee GetPropertySetFunction()
override {
1661 return ObjCTypes.getSetPropertyFn();
1664 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
1665 bool copy)
override {
1666 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1669 llvm::FunctionCallee GetSetStructFunction()
override {
1670 return ObjCTypes.getCopyStructFn();
1673 llvm::FunctionCallee GetGetStructFunction()
override {
1674 return ObjCTypes.getCopyStructFn();
1677 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override {
1678 return ObjCTypes.getCppAtomicObjectFunction();
1681 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override {
1682 return ObjCTypes.getCppAtomicObjectFunction();
1685 llvm::FunctionCallee EnumerationMutationFunction()
override {
1686 return ObjCTypes.getEnumerationMutationFn();
1694 bool ClearInsertionPoint=
true)
override;
1696 Address AddrWeakObj)
override;
1698 llvm::Value *src,
Address edst)
override;
1700 llvm::Value *src,
Address dest,
1701 bool threadlocal =
false)
override;
1703 llvm::Value *src,
Address dest,
1704 llvm::Value *ivarOffset)
override;
1706 llvm::Value *src,
Address dest)
override;
1709 llvm::Value *size)
override;
1712 unsigned CVRQualifiers)
override;
1720struct NullReturnState {
1721 llvm::BasicBlock *NullBB =
nullptr;
1722 NullReturnState() =
default;
1735 CGF.
Builder.CreateCondBr(isNull, NullBB, callBB);
1750 if (!NullBB)
return result;
1754 llvm::BasicBlock *contBB =
nullptr;
1757 llvm::BasicBlock *callBB = CGF.
Builder.GetInsertBlock();
1772 assert(CGF.
Builder.GetInsertBlock() == NullBB);
1792 llvm::PHINode *phi = CGF.
Builder.CreatePHI(null->getType(), 2);
1794 phi->addIncoming(null, NullBB);
1803 assert(result.
isAggregate() &&
"null init of non-aggregate result?");
1812 CodeGenFunction::ComplexPairTy callResult = result.
getComplexVal();
1815 llvm::Type *scalarTy = callResult.first->getType();
1816 llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);
1819 llvm::PHINode *real = CGF.
Builder.CreatePHI(scalarTy, 2);
1820 real->addIncoming(callResult.first, callBB);
1821 real->addIncoming(scalarZero, NullBB);
1822 llvm::PHINode *imag = CGF.
Builder.CreatePHI(scalarTy, 2);
1823 imag->addIncoming(callResult.second, callBB);
1824 imag->addIncoming(scalarZero, NullBB);
1835 llvm::GlobalVariable *
C,
unsigned idx0,
1837 llvm::Value *Idxs[] = {
1838 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1839 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
1841 return llvm::ConstantExpr::getGetElementPtr(
C->getValueType(),
C, Idxs);
1848 if (OID->
hasAttr<ObjCExceptionAttr>())
1855static llvm::GlobalValue::LinkageTypes
1857 if (CGM.
getTriple().isOSBinFormatMachO() &&
1858 (Section.empty() || Section.starts_with(
"__DATA")))
1859 return llvm::GlobalValue::InternalLinkage;
1860 return llvm::GlobalValue::PrivateLinkage;
1864static llvm::GlobalVariable *
1867 std::string SectionName;
1868 if (CGM.
getTriple().isOSBinFormatMachO())
1869 SectionName =
"__DATA, __objc_const";
1870 auto *GV = Builder.finishAndCreateGlobal(
1873 GV->setSection(SectionName);
1889 return EmitClassRef(CGF, ID);
1894 return EmitSelector(CGF, Sel);
1897 return EmitSelectorAddr(Sel);
1904llvm::Constant *CGObjCMac::GetEHType(
QualType T) {
1918 llvm_unreachable(
"asking for catch type for ObjC type in fragile runtime");
1941CGObjCCommonMac::GenerateConstantString(
const StringLiteral *SL) {
1944 : GenerateConstantNSString(SL));
1947static llvm::StringMapEntry<llvm::GlobalVariable *> &
1950 StringRef String = Literal->getString();
1951 StringLength = String.size();
1952 return *Map.insert(std::make_pair(String,
nullptr)).first;
1955llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
1956 if (llvm::Value *
V = ConstantStringClassRef)
1957 return cast<llvm::Constant>(
V);
1961 StringClass.empty() ?
"_NSConstantStringClassReference"
1962 :
"_" + StringClass +
"ClassReference";
1964 llvm::Type *PTy = llvm::ArrayType::get(CGM.
IntTy, 0);
1966 ConstantStringClassRef = GV;
1970llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
1971 if (llvm::Value *
V = ConstantStringClassRef)
1972 return cast<llvm::Constant>(
V);
1976 StringClass.empty() ?
"OBJC_CLASS_$_NSConstantString"
1977 :
"OBJC_CLASS_$_" + StringClass;
1979 ConstantStringClassRef = GV;
1984CGObjCCommonMac::GenerateConstantNSString(
const StringLiteral *Literal) {
1985 unsigned StringLength = 0;
1986 llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
1989 if (
auto *
C = Entry.second)
1994 llvm::Constant *
Class = getNSConstantStringClassRef();
1997 if (!NSConstantStringType) {
1998 NSConstantStringType =
2000 "struct.__builtin_NSString");
2004 auto Fields = Builder.beginStruct(NSConstantStringType);
2011 llvm::ConstantDataArray::getString(VMContext, Entry.first());
2013 llvm::GlobalValue::LinkageTypes
Linkage = llvm::GlobalValue::PrivateLinkage;
2014 bool isConstant = !CGM.
getLangOpts().WritableStrings;
2016 auto *GV =
new llvm::GlobalVariable(CGM.
getModule(),
C->getType(), isConstant,
2018 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2021 GV->setAlignment(llvm::Align(1));
2025 Fields.addInt(CGM.
IntTy, StringLength);
2029 GV = Fields.finishAndCreateGlobal(
"_unnamed_nsstring_", Alignment,
2031 llvm::GlobalVariable::PrivateLinkage);
2032 const char *NSStringSection =
"__OBJC,__cstring_object,regular,no_dead_strip";
2033 const char *NSStringNonFragileABISection =
2034 "__DATA,__objc_stringobj,regular,no_dead_strip";
2037 ? NSStringNonFragileABISection
2057 bool isCategoryImpl,
2058 llvm::Value *Receiver,
2059 bool IsClassMessage,
2066 llvm::Value *ReceiverAsObject =
2067 CGF.
Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
2072 llvm::Type *ClassTyPtr = llvm::PointerType::getUnqual(ObjCTypes.ClassTy);
2074 if (IsClassMessage) {
2075 if (isCategoryImpl) {
2082 Target = EmitClassRef(CGF,
Class->getSuperClass());
2087 llvm::Constant *MetaClassPtr = EmitMetaClassRef(
Class);
2088 llvm::Value *SuperPtr =
2094 }
else if (isCategoryImpl)
2095 Target = EmitClassRef(CGF,
Class->getSuperClass());
2097 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
2104 llvm::Type *ClassTy =
2108 return EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper.
getPointer(),
2109 ObjCTypes.SuperPtrCTy,
true, CallArgs, Method, Class,
2118 llvm::Value *Receiver,
2122 return EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
2124 Method, Class, ObjCTypes);
2138 const ObjCCommonTypesHelper &ObjCTypes) {
2141 llvm::Value *SelValue = llvm::UndefValue::get(Types.ConvertType(selTy));
2145 Arg0 = CGF.
Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
2152 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
2157 "Result type mismatch!");
2159 bool ReceiverCanBeNull =
2160 canMessageReceiverBeNull(CGF, Method, IsSuper, ClassReceiver, Arg0);
2162 bool RequiresNullCheck =
false;
2163 bool RequiresSelValue =
true;
2165 llvm::FunctionCallee
Fn =
nullptr;
2171 RequiresSelValue =
false;
2173 if (ReceiverCanBeNull) RequiresNullCheck =
true;
2174 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
2175 : ObjCTypes.getSendStretFn(IsSuper);
2177 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
2178 : ObjCTypes.getSendFpretFn(IsSuper);
2180 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
2181 : ObjCTypes.getSendFp2retFn(IsSuper);
2186 RequiresNullCheck =
true;
2187 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
2188 : ObjCTypes.getSendFn(IsSuper);
2192 llvm::Constant *BitcastFn = cast<llvm::Constant>(
2193 CGF.
Builder.CreateBitCast(
Fn.getCallee(), MSI.MessengerType));
2198 RequiresNullCheck =
false;
2202 RequiresNullCheck =
true;
2204 NullReturnState nullReturn;
2205 if (RequiresNullCheck) {
2206 nullReturn.init(CGF, Arg0);
2210 if (RequiresSelValue) {
2211 SelValue = GetSelector(CGF, Sel);
2215 llvm::CallBase *CallSite;
2217 RValue rvalue = CGF.
EmitCall(MSI.CallInfo, Callee, Return, ActualArgs,
2222 if (Method && Method->
hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
2223 CallSite->setDoesNotReturn();
2226 return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs,
2227 RequiresNullCheck ? Method :
nullptr);
2231 bool pointee =
false) {
2244 switch (ownership) {
2251 llvm_unreachable(
"bad objc ownership");
2259 if (Ctx.
getLangOpts().getGC() != LangOptions::NonGC) {
2271 IvarInfo(
CharUnits offset, uint64_t sizeInWords)
2272 : Offset(offset), SizeInWords(sizeInWords) {}
2275 bool operator<(
const IvarInfo &other)
const {
2276 return Offset < other.Offset;
2281 class IvarLayoutBuilder {
2292 bool ForStrongLayout;
2295 bool IsDisordered =
false;
2301 CharUnits instanceEnd,
bool forStrongLayout)
2302 : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
2303 ForStrongLayout(forStrongLayout) {
2308 template <
class Iterator,
class GetOffsetFn>
2309 void visitAggregate(Iterator begin, Iterator end,
2311 const GetOffsetFn &getOffset);
2319 bool hasBitmapData()
const {
return !IvarsInfo.empty(); }
2321 llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
2325 const unsigned char *
s = buffer.data();
2326 for (
unsigned i = 0, e = buffer.size(); i < e; i++)
2328 printf(
"0x0%x%s",
s[i],
s[i] != 0 ?
", " :
"");
2330 printf(
"0x%x%s",
s[i],
s[i] != 0 ?
", " :
"");
2336llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(
CodeGenModule &CGM,
2339 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2340 if (CGM.
getLangOpts().getGC() == LangOptions::NonGC)
2346 builder.visitBlock(blockInfo);
2348 if (!builder.hasBitmapData())
2352 llvm::Constant *
C = builder.buildBitmap(*
this, buffer);
2353 if (CGM.
getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
2354 printf(
"\n block variable layout for block: ");
2355 builder.dump(buffer);
2361void IvarLayoutBuilder::visitBlock(
const CGBlockInfo &blockInfo) {
2374 for (
const auto &CI :
blockDecl->captures()) {
2375 const VarDecl *variable = CI.getVariable();
2387 if (fieldOffset < lastFieldOffset)
2388 IsDisordered =
true;
2389 lastFieldOffset = fieldOffset;
2393 IvarsInfo.push_back(IvarInfo(fieldOffset, 1));
2397 assert(!
type->isArrayType() &&
"array variable should not be caught");
2399 visitRecord(record, fieldOffset);
2408 IvarsInfo.push_back(IvarInfo(fieldOffset, 1));
2433void CGObjCCommonMac::UpdateRunSkipBlockVars(
bool IsByref,
2439 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
2442 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
2445 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
2448 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
2451 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2456void CGObjCCommonMac::BuildRCRecordLayout(
const llvm::StructLayout *RecLayout,
2461 bool IsUnion = (RD && RD->
isUnion());
2464 const FieldDecl *LastFieldBitfieldOrUnnamed =
nullptr;
2468 if (RecFields.empty())
2472 for (
unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2481 if (!
Field->getIdentifier() ||
Field->isBitField()) {
2482 LastFieldBitfieldOrUnnamed =
Field;
2483 LastBitfieldOrUnnamedOffset = FieldOffset;
2487 LastFieldBitfieldOrUnnamed =
nullptr;
2494 BytePos + FieldOffset, HasUnion);
2499 auto *CArray = cast<ConstantArrayType>(Array);
2500 uint64_t ElCount = CArray->getZExtSize();
2501 assert(CArray &&
"only array with known element size is supported");
2502 FQT = CArray->getElementType();
2504 auto *CArray = cast<ConstantArrayType>(Array);
2505 ElCount *= CArray->getZExtSize();
2506 FQT = CArray->getElementType();
2509 int OldIndex = RunSkipBlockVars.size() - 1;
2511 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset, HasUnion);
2516 for (
int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
2518 for (
int i = OldIndex+1; i <= FirstIndex; ++i)
2519 RunSkipBlockVars.push_back(
2520 RUN_SKIP(RunSkipBlockVars[i].opcode,
2521 RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
2522 RunSkipBlockVars[i].block_var_size));
2530 if (UnionIvarSize > MaxUnionSize) {
2531 MaxUnionSize = UnionIvarSize;
2533 MaxFieldOffset = FieldOffset;
2536 UpdateRunSkipBlockVars(
false,
2537 getBlockCaptureLifetime(FQT, ByrefLayout),
2538 BytePos + FieldOffset,
2543 if (LastFieldBitfieldOrUnnamed) {
2544 if (LastFieldBitfieldOrUnnamed->
isBitField()) {
2548 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
2549 ((BitFieldSize % ByteSizeInBits) != 0);
2551 Size += LastBitfieldOrUnnamedOffset;
2552 UpdateRunSkipBlockVars(
false,
2553 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->
getType(),
2555 BytePos + LastBitfieldOrUnnamedOffset,
2558 assert(!LastFieldBitfieldOrUnnamed->
getIdentifier() &&
"Expected unnamed");
2562 UpdateRunSkipBlockVars(
false,
2563 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->
getType(),
2565 BytePos + LastBitfieldOrUnnamedOffset,
2571 UpdateRunSkipBlockVars(
false,
2572 getBlockCaptureLifetime(MaxField->
getType(), ByrefLayout),
2573 BytePos + MaxFieldOffset,
2577void CGObjCCommonMac::BuildRCBlockVarRecordLayout(
const RecordType *RT,
2584 const llvm::StructLayout *RecLayout =
2585 CGM.
getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
2587 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
2599uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2602 if (Layout.size() <= 3) {
2603 unsigned size = Layout.size();
2604 unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
2606 enum BLOCK_LAYOUT_OPCODE opcode ;
2610 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2611 if (opcode == BLOCK_LAYOUT_STRONG)
2612 strong_word_count = (inst & 0xF)+1;
2616 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2617 if (opcode == BLOCK_LAYOUT_BYREF)
2618 byref_word_count = (inst & 0xF)+1;
2622 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2623 if (opcode == BLOCK_LAYOUT_WEAK)
2624 weak_word_count = (inst & 0xF)+1;
2631 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2632 if (opcode == BLOCK_LAYOUT_STRONG) {
2633 strong_word_count = (inst & 0xF)+1;
2635 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2636 if (opcode == BLOCK_LAYOUT_BYREF)
2637 byref_word_count = (inst & 0xF)+1;
2638 else if (opcode == BLOCK_LAYOUT_WEAK)
2639 weak_word_count = (inst & 0xF)+1;
2643 else if (opcode == BLOCK_LAYOUT_BYREF) {
2644 byref_word_count = (inst & 0xF)+1;
2646 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2647 if (opcode == BLOCK_LAYOUT_WEAK)
2648 weak_word_count = (inst & 0xF)+1;
2658 opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2659 if (opcode == BLOCK_LAYOUT_STRONG)
2660 strong_word_count = (inst & 0xF)+1;
2661 else if (opcode == BLOCK_LAYOUT_BYREF)
2662 byref_word_count = (inst & 0xF)+1;
2663 else if (opcode == BLOCK_LAYOUT_WEAK)
2664 weak_word_count = (inst & 0xF)+1;
2676 if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
2680 (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
2682 if (size == count) {
2683 if (strong_word_count)
2684 Result = strong_word_count;
2686 if (byref_word_count)
2687 Result += byref_word_count;
2689 if (weak_word_count)
2690 Result += weak_word_count;
2696llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(
bool ComputeByrefLayout) {
2697 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2698 if (RunSkipBlockVars.empty())
2702 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2706 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2709 unsigned size = RunSkipBlockVars.size();
2710 for (
unsigned i = 0; i < size; i++) {
2711 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2712 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2713 CharUnits end_byte_pos = start_byte_pos;
2716 if (opcode == RunSkipBlockVars[j].opcode) {
2717 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2724 end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2727 RunSkipBlockVars[j].block_var_bytepos -
2728 RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
2729 size_in_bytes += gap;
2732 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2733 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2734 size_in_bytes -= residue_in_bytes;
2735 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2738 unsigned size_in_words = size_in_bytes.
getQuantity() / WordSizeInBytes;
2739 while (size_in_words >= 16) {
2742 unsigned char inst = (opcode << 4) | 0xf;
2743 Layout.push_back(inst);
2744 size_in_words -= 16;
2746 if (size_in_words > 0) {
2749 unsigned char inst = (opcode << 4) | (size_in_words-1);
2750 Layout.push_back(inst);
2753 unsigned char inst =
2754 (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.
getQuantity()-1);
2755 Layout.push_back(inst);
2759 while (!Layout.empty()) {
2760 unsigned char inst = Layout.back();
2761 enum BLOCK_LAYOUT_OPCODE opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2762 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2768 uint64_t Result = InlineLayoutInstruction(Layout);
2772 if (ComputeByrefLayout)
2773 printf(
"\n Inline BYREF variable layout: ");
2775 printf(
"\n Inline block variable layout: ");
2776 printf(
"0x0%" PRIx64
"", Result);
2777 if (
auto numStrong = (Result & 0xF00) >> 8)
2778 printf(
", BL_STRONG:%d", (
int) numStrong);
2779 if (
auto numByref = (Result & 0x0F0) >> 4)
2780 printf(
", BL_BYREF:%d", (
int) numByref);
2781 if (
auto numWeak = (Result & 0x00F) >> 0)
2782 printf(
", BL_WEAK:%d", (
int) numWeak);
2783 printf(
", BL_OPERATOR:0\n");
2785 return llvm::ConstantInt::get(CGM.
IntPtrTy, Result);
2788 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2789 Layout.push_back(inst);
2791 for (
unsigned i = 0, e = Layout.size(); i != e; i++)
2792 BitMap += Layout[i];
2795 if (ComputeByrefLayout)
2796 printf(
"\n Byref variable layout: ");
2798 printf(
"\n Block variable layout: ");
2799 for (
unsigned i = 0, e = BitMap.size(); i != e; i++) {
2800 unsigned char inst = BitMap[i];
2801 enum BLOCK_LAYOUT_OPCODE opcode = (
enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2804 case BLOCK_LAYOUT_OPERATOR:
2808 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2809 printf(
"BL_NON_OBJECT_BYTES:");
2811 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2812 printf(
"BL_NON_OBJECT_WORD:");
2814 case BLOCK_LAYOUT_STRONG:
2817 case BLOCK_LAYOUT_BYREF:
2820 case BLOCK_LAYOUT_WEAK:
2823 case BLOCK_LAYOUT_UNRETAINED:
2824 printf(
"BL_UNRETAINED:");
2829 printf(
"%d", (inst & 0xf) + delta);
2837 auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
2845 bool HasCopyDisposeHelpers) {
2847 for (
const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) {
2848 if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) {
2852 }
else if (HasCopyDisposeHelpers) {
2860 case CGObjCCommonMac::BLOCK_LAYOUT_STRONG:
2863 case CGObjCCommonMac::BLOCK_LAYOUT_BYREF:
2866 case CGObjCCommonMac::BLOCK_LAYOUT_WEAK:
2873 Str += llvm::to_string(R.block_var_bytepos.getQuantity());
2874 Str +=
"l" + llvm::to_string(R.block_var_size.getQuantity());
2879void CGObjCCommonMac::fillRunSkipBlockVars(
CodeGenModule &CGM,
2881 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
2883 RunSkipBlockVars.clear();
2884 bool hasUnion =
false;
2888 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2893 const llvm::StructLayout *layout =
2903 for (
const auto &CI :
blockDecl->captures()) {
2904 const VarDecl *variable = CI.getVariable();
2915 assert(!
type->isArrayType() &&
"array variable should not be caught");
2918 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2926 UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(
type,
false),
2927 fieldOffset, fieldSize);
2934 fillRunSkipBlockVars(CGM, blockInfo);
2935 return getBitmapBlockLayout(
false);
2938std::string CGObjCCommonMac::getRCBlockLayoutStr(
CodeGenModule &CGM,
2940 fillRunSkipBlockVars(CGM, blockInfo);
2946 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
2947 assert(!
T->
isArrayType() &&
"__block array variable should not be caught");
2949 RunSkipBlockVars.clear();
2950 bool hasUnion =
false;
2952 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion,
true );
2953 llvm::Constant *Result = getBitmapBlockLayout(
true);
2954 if (isa<llvm::ConstantInt>(Result))
2955 Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.
Int8PtrTy);
2958 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.
Int8PtrTy);
2968 return GetProtocolRef(PD);
2980 GetOrEmitProtocol(PD);
2983llvm::Constant *CGObjCCommonMac::GetProtocolRef(
const ObjCProtocolDecl *PD) {
2985 return GetOrEmitProtocol(PD);
2987 return GetOrEmitProtocolRef(PD);
2990llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime(
2993 ObjCCommonTypesHelper &ObjCTypes) {
2994 llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn();
2996 llvm::Value *className = CGF.
CGM
2998 ID->getObjCRuntimeNameAsString()))
3002 CGF.
Builder.CreateBitCast(className,
3005 llvm::CallInst *call = CGF.
Builder.CreateCall(lookUpClassFn, className);
3006 call->setDoesNotThrow();
3023 llvm::GlobalVariable *Entry = Protocols[PD->
getIdentifier()];
3026 if (Entry && Entry->hasInitializer())
3038 auto methodLists = ProtocolMethodLists::get(PD);
3041 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
3042 values.add(EmitProtocolExtension(PD, methodLists));
3044 values.add(EmitProtocolList(
"OBJC_PROTOCOL_REFS_" + PD->
getName(),
3046 values.add(methodLists.emitMethodList(
this, PD,
3047 ProtocolMethodLists::RequiredInstanceMethods));
3048 values.add(methodLists.emitMethodList(
this, PD,
3049 ProtocolMethodLists::RequiredClassMethods));
3053 assert(Entry->hasPrivateLinkage());
3054 values.finishAndSetAsInitializer(Entry);
3056 Entry = values.finishAndCreateGlobal(
"OBJC_PROTOCOL_" + PD->
getName(),
3059 llvm::GlobalValue::PrivateLinkage);
3060 Entry->setSection(
"__OBJC,__protocol,regular,no_dead_strip");
3069llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(
const ObjCProtocolDecl *PD) {
3070 llvm::GlobalVariable *&Entry = Protocols[PD->
getIdentifier()];
3076 Entry =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ProtocolTy,
3077 false, llvm::GlobalValue::PrivateLinkage,
3078 nullptr,
"OBJC_PROTOCOL_" + PD->
getName());
3079 Entry->setSection(
"__OBJC,__protocol,regular,no_dead_strip");
3081 Entry->setAlignment(llvm::Align(4));
3099 const ProtocolMethodLists &methodLists) {
3100 auto optInstanceMethods =
3101 methodLists.emitMethodList(
this, PD,
3102 ProtocolMethodLists::OptionalInstanceMethods);
3103 auto optClassMethods =
3104 methodLists.emitMethodList(
this, PD,
3105 ProtocolMethodLists::OptionalClassMethods);
3107 auto extendedMethodTypes =
3108 EmitProtocolMethodTypes(
"OBJC_PROTOCOL_METHOD_TYPES_" + PD->
getName(),
3109 methodLists.emitExtendedTypesArray(
this),
3112 auto instanceProperties =
3113 EmitPropertyList(
"OBJC_$_PROP_PROTO_LIST_" + PD->
getName(),
nullptr, PD,
3115 auto classProperties =
3116 EmitPropertyList(
"OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->
getName(),
nullptr,
3117 PD, ObjCTypes,
true);
3120 if (optInstanceMethods->isNullValue() &&
3121 optClassMethods->isNullValue() &&
3122 extendedMethodTypes->isNullValue() &&
3123 instanceProperties->isNullValue() &&
3124 classProperties->isNullValue()) {
3125 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
3129 CGM.
getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
3132 auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
3133 values.addInt(ObjCTypes.IntTy, size);
3134 values.add(optInstanceMethods);
3135 values.add(optClassMethods);
3136 values.add(instanceProperties);
3137 values.add(extendedMethodTypes);
3138 values.add(classProperties);
3141 return CreateMetadataVar(
"_OBJC_PROTOCOLEXT_" + PD->
getName(), values,
3153CGObjCMac::EmitProtocolList(Twine name,
3157 auto PDs = GetRuntimeProtocolList(begin, end);
3159 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
3162 auto values = builder.beginStruct();
3165 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
3168 auto countSlot = values.addPlaceholder();
3170 auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
3171 for (
const auto *Proto : PDs)
3172 refsArray.add(GetProtocolRef(Proto));
3174 auto count = refsArray.size();
3177 refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);
3179 refsArray.finishAndAddTo(values);
3180 values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);
3183 if (CGM.
getTriple().isOSBinFormatMachO())
3184 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3186 llvm::GlobalVariable *GV =
3187 CreateMetadataVar(name, values, section, CGM.
getPointerAlign(),
false);
3195 bool IsClassProperty) {
3197 if (IsClassProperty != PD->isClassProperty())
3201 Properties.push_back(PD);
3220llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
3221 const Decl *Container,
3223 const ObjCCommonTypesHelper &ObjCTypes,
3224 bool IsClassProperty) {
3225 if (IsClassProperty) {
3229 if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
3230 (Triple.isiOS() && Triple.isOSVersionLT(9)))
3231 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3239 for (
auto *PD : ClassExt->properties()) {
3240 if (IsClassProperty != PD->isClassProperty())
3242 if (PD->isDirectProperty())
3245 Properties.push_back(PD);
3249 if (IsClassProperty != PD->isClassProperty())
3255 if (PD->isDirectProperty())
3257 Properties.push_back(PD);
3261 for (
const auto *
P : OID->all_referenced_protocols())
3265 for (
const auto *
P : CD->protocols())
3270 if (Properties.empty())
3271 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3273 unsigned propertySize =
3277 auto values = builder.beginStruct();
3278 values.addInt(ObjCTypes.IntTy, propertySize);
3279 values.addInt(ObjCTypes.IntTy, Properties.size());
3280 auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
3281 for (
auto PD : Properties) {
3282 auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
3284 property.add(GetPropertyTypeString(PD, Container));
3285 property.finishAndAddTo(propertiesArray);
3287 propertiesArray.finishAndAddTo(values);
3290 if (CGM.
getTriple().isOSBinFormatMachO())
3291 Section = (ObjCABI == 2) ?
"__DATA, __objc_const"
3292 :
"__OBJC,__property,regular,no_dead_strip";
3294 llvm::GlobalVariable *GV =
3295 CreateMetadataVar(Name, values, Section, CGM.
getPointerAlign(),
true);
3300CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
3302 const ObjCCommonTypesHelper &ObjCTypes) {
3304 if (MethodTypes.empty())
3305 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
3307 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3308 MethodTypes.size());
3309 llvm::Constant *
Init = llvm::ConstantArray::get(AT, MethodTypes);
3312 if (CGM.
getTriple().isOSBinFormatMachO() && ObjCABI == 2)
3313 Section =
"__DATA, __objc_const";
3315 llvm::GlobalVariable *GV =
3344 llvm::raw_svector_ostream(ExtName) <<
Interface->getName() <<
'_'
3348 auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);
3356 for (
const auto *MD : OCD->
methods()) {
3357 if (!MD->isDirectMethod())
3358 Methods[
unsigned(MD->isClassMethod())].push_back(MD);
3361 Values.add(GetClassName(OCD->
getName()));
3362 Values.add(GetClassName(
Interface->getObjCRuntimeNameAsString()));
3363 LazySymbols.insert(
Interface->getIdentifier());
3365 Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
3366 Methods[InstanceMethods]));
3367 Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
3368 Methods[ClassMethods]));
3371 EmitProtocolList(
"OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
3374 Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
3376 Values.addInt(ObjCTypes.IntTy, Size);
3380 Values.add(EmitPropertyList(
"_OBJC_$_PROP_LIST_" + ExtName.str(),
3382 Values.add(EmitPropertyList(
"_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(),
3385 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3386 Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
3389 llvm::GlobalVariable *GV =
3390 CreateMetadataVar(
"OBJC_CATEGORY_" + ExtName.str(), Values,
3391 "__OBJC,__category,regular,no_dead_strip",
3393 DefinedCategories.push_back(GV);
3394 DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
3396 MethodDefinitions.clear();
3456 for (
auto *field : recType->getDecl()->fields()) {
3471 assert(CGM.
getLangOpts().getGC() == LangOptions::NonGC);
3474 ID->getClassInterface()->all_declared_ivar_begin();
3475 ivar; ivar = ivar->getNextIvar()) {
3505 DefinedSymbols.insert(RuntimeName);
3507 std::string ClassName =
ID->getNameAsString();
3511 llvm::Constant *Protocols =
3512 EmitProtocolList(
"OBJC_CLASS_PROTOCOLS_" +
ID->getName(),
3513 Interface->all_referenced_protocol_begin(),
3514 Interface->all_referenced_protocol_end());
3516 if (
ID->hasNonZeroConstructors() ||
ID->hasDestructors())
3519 bool hasMRCWeak =
false;
3539 for (
const auto *MD :
ID->methods()) {
3540 if (!MD->isDirectMethod())
3541 Methods[
unsigned(MD->isClassMethod())].push_back(MD);
3544 for (
const auto *PID :
ID->property_impls()) {
3546 if (PID->getPropertyDecl()->isDirectProperty())
3549 if (GetMethodDefinition(MD))
3550 Methods[InstanceMethods].push_back(MD);
3552 if (GetMethodDefinition(MD))
3553 Methods[InstanceMethods].push_back(MD);
3558 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3559 values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
3562 LazySymbols.insert(Super->getIdentifier());
3564 values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
3566 values.addNullPointer(ObjCTypes.ClassPtrTy);
3568 values.add(GetClassName(
ID->getObjCRuntimeNameAsString()));
3570 values.addInt(ObjCTypes.LongTy, 0);
3571 values.addInt(ObjCTypes.LongTy, Flags);
3572 values.addInt(ObjCTypes.LongTy,
Size.getQuantity());
3573 values.add(EmitIvarList(ID,
false));
3574 values.add(emitMethodList(
ID->getName(), MethodListType::InstanceMethods,
3575 Methods[InstanceMethods]));
3577 values.addNullPointer(ObjCTypes.CachePtrTy);
3578 values.add(Protocols);
3580 values.add(EmitClassExtension(ID, Size, hasMRCWeak,
3583 std::string Name(
"OBJC_CLASS_");
3585 const char *Section =
"__OBJC,__class,regular,no_dead_strip";
3587 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3589 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3590 "Forward metaclass reference has incorrect type.");
3591 values.finishAndSetAsInitializer(GV);
3592 GV->setSection(Section);
3596 GV = CreateMetadataVar(Name, values, Section, CGM.
getPointerAlign(),
true);
3597 DefinedClasses.push_back(GV);
3598 ImplementedClasses.push_back(
Interface);
3600 MethodDefinitions.clear();
3604 llvm::Constant *Protocols,
3613 auto values = builder.beginStruct(ObjCTypes.ClassTy);
3623 values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
3625 values.addNullPointer(ObjCTypes.ClassPtrTy);
3627 values.add(GetClassName(
ID->getObjCRuntimeNameAsString()));
3629 values.addInt(ObjCTypes.LongTy, 0);
3630 values.addInt(ObjCTypes.LongTy, Flags);
3631 values.addInt(ObjCTypes.LongTy, Size);
3632 values.add(EmitIvarList(ID,
true));
3633 values.add(emitMethodList(
ID->getName(), MethodListType::ClassMethods,
3636 values.addNullPointer(ObjCTypes.CachePtrTy);
3637 values.add(Protocols);
3639 values.addNullPointer(ObjCTypes.Int8PtrTy);
3644 std::string Name(
"OBJC_METACLASS_");
3645 Name +=
ID->getName();
3648 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3650 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3651 "Forward metaclass reference has incorrect type.");
3652 values.finishAndSetAsInitializer(GV);
3656 llvm::GlobalValue::PrivateLinkage);
3658 GV->setSection(
"__OBJC,__meta_class,regular,no_dead_strip");
3665 std::string Name =
"OBJC_METACLASS_" +
ID->getNameAsString();
3675 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3677 GV =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ClassTy,
false,
3678 llvm::GlobalValue::PrivateLinkage,
nullptr,
3681 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3682 "Forward metaclass reference has incorrect type.");
3687 std::string Name =
"OBJC_CLASS_" +
ID->getNameAsString();
3688 llvm::GlobalVariable *GV = CGM.
getModule().getGlobalVariable(Name,
true);
3691 GV =
new llvm::GlobalVariable(CGM.
getModule(), ObjCTypes.ClassTy,
false,
3692 llvm::GlobalValue::PrivateLinkage,
nullptr,
3695 assert(GV->getValueType() == ObjCTypes.ClassTy &&
3696 "Forward class metadata reference has incorrect type.");
3716 llvm::Constant *layout;
3718 layout = llvm::ConstantPointerNull::get(CGM.
Int8PtrTy);
3725 llvm::Constant *propertyList =
3726 EmitPropertyList((isMetaclass ? Twine(
"_OBJC_$_CLASS_PROP_LIST_")
3727 : Twine(
"_OBJC_$_PROP_LIST_"))
3729 ID,
ID->getClassInterface(), ObjCTypes, isMetaclass);
3732 if (layout->isNullValue() && propertyList->isNullValue()) {
3733 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
3737 CGM.
getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
3740 auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
3741 values.addInt(ObjCTypes.IntTy, size);
3743 values.add(propertyList);
3745 return CreateMetadataVar(
"OBJC_CLASSEXT_" +
ID->getName(), values,
3746 "__OBJC,__class_ext,regular,no_dead_strip",
3770 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
3775 auto ivarList = builder.beginStruct();
3776 auto countSlot = ivarList.addPlaceholder();
3777 auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);
3782 if (!IVD->getDeclName())
3785 auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
3786 ivar.add(GetMethodVarName(IVD->getIdentifier()));
3787 ivar.add(GetMethodVarType(IVD));
3788 ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
3789 ivar.finishAndAddTo(ivars);
3793 auto count = ivars.size();
3797 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
3800 ivars.finishAndAddTo(ivarList);
3801 ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);
3803 llvm::GlobalVariable *GV;
3804 GV = CreateMetadataVar(
"OBJC_INSTANCE_VARIABLES_" +
ID->getName(), ivarList,
3805 "__OBJC,__instance_vars,regular,no_dead_strip",
3818 auto description = builder.
beginStruct(ObjCTypes.MethodDescriptionTy);
3819 description.add(GetMethodVarName(MD->
getSelector()));
3820 description.add(GetMethodVarType(MD));
3821 description.finishAndAddTo(builder);
3833 llvm::Function *fn = GetMethodDefinition(MD);
3834 assert(fn &&
"no definition registered for method");
3836 auto method = builder.
beginStruct(ObjCTypes.MethodTy);
3838 method.add(GetMethodVarType(MD));
3840 method.finishAndAddTo(builder);
3856llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
3860 bool forProtocol =
false;
3862 case MethodListType::CategoryInstanceMethods:
3863 prefix =
"OBJC_CATEGORY_INSTANCE_METHODS_";
3864 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3865 forProtocol =
false;
3867 case MethodListType::CategoryClassMethods:
3868 prefix =
"OBJC_CATEGORY_CLASS_METHODS_";
3869 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3870 forProtocol =
false;
3872 case MethodListType::InstanceMethods:
3873 prefix =
"OBJC_INSTANCE_METHODS_";
3874 section =
"__OBJC,__inst_meth,regular,no_dead_strip";
3875 forProtocol =
false;
3877 case MethodListType::ClassMethods:
3878 prefix =
"OBJC_CLASS_METHODS_";
3879 section =
"__OBJC,__cls_meth,regular,no_dead_strip";
3880 forProtocol =
false;
3882 case MethodListType::ProtocolInstanceMethods:
3883 prefix =
"OBJC_PROTOCOL_INSTANCE_METHODS_";
3884 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3887 case MethodListType::ProtocolClassMethods:
3888 prefix =
"OBJC_PROTOCOL_CLASS_METHODS_";
3889 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3892 case MethodListType::OptionalProtocolInstanceMethods:
3893 prefix =
"OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
3894 section =
"__OBJC,__cat_inst_meth,regular,no_dead_strip";
3897 case MethodListType::OptionalProtocolClassMethods:
3898 prefix =
"OBJC_PROTOCOL_CLASS_METHODS_OPT_";
3899 section =
"__OBJC,__cat_cls_meth,regular,no_dead_strip";
3905 if (methods.empty())
3906 return llvm::Constant::getNullValue(forProtocol
3907 ? ObjCTypes.MethodDescriptionListPtrTy
3908 : ObjCTypes.MethodListPtrTy);
3915 values.addInt(ObjCTypes.IntTy, methods.size());
3916 auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
3917 for (
auto MD : methods) {
3918 emitMethodDescriptionConstant(methodArray, MD);
3920 methodArray.finishAndAddTo(values);
3922 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3930 values.addNullPointer(ObjCTypes.Int8PtrTy);
3931 values.addInt(ObjCTypes.IntTy, methods.size());
3932 auto methodArray = values.beginArray(ObjCTypes.MethodTy);
3933 for (
auto MD : methods) {
3935 emitMethodConstant(methodArray, MD);
3937 methodArray.finishAndAddTo(values);
3939 llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
3944llvm::Function *CGObjCCommonMac::GenerateMethod(
const ObjCMethodDecl *OMD,
3946 llvm::Function *Method;
3949 Method = GenerateDirectMethod(OMD, CD);
3951 auto Name = getSymbolNameForMethod(OMD);
3954 llvm::FunctionType *MethodTy =
3955 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
3957 llvm::Function::Create(MethodTy, llvm::GlobalValue::InternalLinkage,
3961 MethodDefinitions.insert(std::make_pair(OMD, Method));
3970 auto I = DirectMethodDefinitions.find(COMD);
3971 llvm::Function *OldFn =
nullptr, *
Fn =
nullptr;
3973 if (I != DirectMethodDefinitions.end()) {
3989 llvm::FunctionType *MethodTy =
3990 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
3993 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
3995 Fn->takeName(OldFn);
3996 OldFn->replaceAllUsesWith(Fn);
3997 OldFn->eraseFromParent();
4002 auto Name = getSymbolNameForMethod(OMD,
false);
4004 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
4006 DirectMethodDefinitions.insert(std::make_pair(COMD, Fn));
4012void CGObjCCommonMac::GenerateDirectMethodPrologue(
4016 bool ReceiverCanBeNull =
true;
4018 auto selfValue = Builder.CreateLoad(selfAddr);
4036 "GenerateDirectMethod() should be called with the Class Interface");
4049 result = GeneratePossiblySpecializedMessageSend(
4057 ReceiverCanBeNull = isWeakLinkedClass(OID);
4060 if (ReceiverCanBeNull) {
4061 llvm::BasicBlock *SelfIsNilBlock =
4063 llvm::BasicBlock *ContBlock =
4067 auto selfTy = cast<llvm::PointerType>(selfValue->getType());
4068 auto Zero = llvm::ConstantPointerNull::get(selfTy);
4071 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero), SelfIsNilBlock,
4072 ContBlock, MDHelper.createUnlikelyBranchWeights());
4078 Builder.SetInsertPoint(SelfIsNilBlock);
4079 if (!retTy->isVoidType()) {
4087 Builder.SetInsertPoint(ContBlock);
4095 Builder.CreateStore(GetSelector(CGF, OMD),
4100llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
4105 llvm::GlobalValue::LinkageTypes
LT =
4107 llvm::GlobalVariable *GV =
4108 Init.finishAndCreateGlobal(Name, Align,
false,
LT);
4109 if (!Section.empty())
4110 GV->setSection(Section);
4116llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
4117 llvm::Constant *
Init,
4121 llvm::Type *Ty =
Init->getType();
4122 llvm::GlobalValue::LinkageTypes
LT =
4124 llvm::GlobalVariable *GV =
4126 if (!Section.empty())
4127 GV->setSection(Section);
4134llvm::GlobalVariable *
4135CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType
Type,
4136 bool ForceNonFragileABI,
4137 bool NullTerminate) {
4140 case ObjCLabelType::ClassName:
Label =
"OBJC_CLASS_NAME_";
break;
4141 case ObjCLabelType::MethodVarName:
Label =
"OBJC_METH_VAR_NAME_";
break;
4142 case ObjCLabelType::MethodVarType:
Label =
"OBJC_METH_VAR_TYPE_";
break;
4143 case ObjCLabelType::PropertyName:
Label =
"OBJC_PROP_NAME_ATTR_";
break;
4146 bool NonFragile = ForceNonFragileABI || isNonFragileABI();
4150 case ObjCLabelType::ClassName:
4151 Section = NonFragile ?
"__TEXT,__objc_classname,cstring_literals"
4152 :
"__TEXT,__cstring,cstring_literals";
4154 case ObjCLabelType::MethodVarName:
4155 Section = NonFragile ?
"__TEXT,__objc_methname,cstring_literals"
4156 :
"__TEXT,__cstring,cstring_literals";
4158 case ObjCLabelType::MethodVarType:
4159 Section = NonFragile ?
"__TEXT,__objc_methtype,cstring_literals"
4160 :
"__TEXT,__cstring,cstring_literals";
4162 case ObjCLabelType::PropertyName:
4163 Section = NonFragile ?
"__TEXT,__objc_methname,cstring_literals"
4164 :
"__TEXT,__cstring,cstring_literals";
4168 llvm::Constant *
Value =
4169 llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
4170 llvm::GlobalVariable *GV =
4173 llvm::GlobalValue::PrivateLinkage,
Value,
Label);
4174 if (CGM.
getTriple().isOSBinFormatMachO())
4175 GV->setSection(Section);
4176 GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
4183llvm::Function *CGObjCMac::ModuleInitFunction() {
4189llvm::FunctionCallee CGObjCMac::GetPropertyGetFunction() {
4190 return ObjCTypes.getGetPropertyFn();
4193llvm::FunctionCallee CGObjCMac::GetPropertySetFunction() {
4194 return ObjCTypes.getSetPropertyFn();
4197llvm::FunctionCallee CGObjCMac::GetOptimizedPropertySetFunction(
bool atomic,
4199 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
4202llvm::FunctionCallee CGObjCMac::GetGetStructFunction() {
4203 return ObjCTypes.getCopyStructFn();
4206llvm::FunctionCallee CGObjCMac::GetSetStructFunction() {
4207 return ObjCTypes.getCopyStructFn();
4210llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectGetFunction() {
4211 return ObjCTypes.getCppAtomicObjectFunction();
4214llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectSetFunction() {
4215 return ObjCTypes.getCppAtomicObjectFunction();
4218llvm::FunctionCallee CGObjCMac::EnumerationMutationFunction() {
4219 return ObjCTypes.getEnumerationMutationFn();
4223 return EmitTryOrSynchronizedStmt(CGF, S);
4228 return EmitTryOrSynchronizedStmt(CGF, S);
4237 ObjCTypesHelper &ObjCTypes;
4238 PerformFragileFinally(
const Stmt *S,
4242 ObjCTypesHelper *ObjCTypes)
4243 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
4244 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
4249 llvm::BasicBlock *FinallyCallExit =
4251 llvm::BasicBlock *FinallyNoCallExit =
4254 FinallyCallExit, FinallyNoCallExit);
4262 if (isa<ObjCAtTryStmt>(S)) {
4264 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
4266 if (flags.isForEHCleanup())
return;
4270 llvm::Value *CurCleanupDest =
4273 CGF.
EmitStmt(FinallyStmt->getFinallyBody());
4292 class FragileHazards {
4295 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
4297 llvm::InlineAsm *ReadHazard;
4298 llvm::InlineAsm *WriteHazard;
4300 llvm::FunctionType *GetAsmFnType();
4302 void collectLocals();
4308 void emitWriteHazard();
4309 void emitHazardsInNewBlocks();
4321 if (Locals.empty())
return;
4324 for (llvm::Function::iterator
4325 I = CGF.
CurFn->begin(),
E = CGF.
CurFn->end(); I !=
E; ++I)
4326 BlocksBeforeTry.insert(&*I);
4328 llvm::FunctionType *AsmFnTy = GetAsmFnType();
4336 std::string Constraint;
4337 for (
unsigned I = 0,
E = Locals.size(); I !=
E; ++I) {
4338 if (I) Constraint +=
',';
4342 ReadHazard = llvm::InlineAsm::get(AsmFnTy,
"", Constraint,
true,
false);
4350 std::string Constraint;
4351 for (
unsigned I = 0,
E = Locals.size(); I !=
E; ++I) {
4352 if (I) Constraint +=
',';
4353 Constraint +=
"=*m";
4356 WriteHazard = llvm::InlineAsm::get(AsmFnTy,
"", Constraint,
true,
false);
4361void FragileHazards::emitWriteHazard() {
4362 if (Locals.empty())
return;
4365 for (
auto Pair : llvm::enumerate(Locals))
4366 Call->addParamAttr(Pair.index(), llvm::Attribute::get(
4368 cast<llvm::AllocaInst>(Pair.value())->getAllocatedType()));
4371void FragileHazards::emitReadHazard(
CGBuilderTy &Builder) {
4372 assert(!Locals.empty());
4373 llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
4374 call->setDoesNotThrow();
4376 for (
auto Pair : llvm::enumerate(Locals))
4377 call->addParamAttr(Pair.index(), llvm::Attribute::get(
4378 Builder.getContext(), llvm::Attribute::ElementType,
4379 cast<llvm::AllocaInst>(Pair.value())->getAllocatedType()));
4384void FragileHazards::emitHazardsInNewBlocks() {
4385 if (Locals.empty())
return;
4390 for (llvm::Function::iterator
4391 FI = CGF.
CurFn->begin(), FE = CGF.
CurFn->end(); FI != FE; ++FI) {
4392 llvm::BasicBlock &BB = *FI;
4393 if (BlocksBeforeTry.count(&BB))
continue;
4396 for (llvm::BasicBlock::iterator
4397 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
4398 llvm::Instruction &I = *BI;
4402 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I))
4404 if (isa<llvm::IntrinsicInst>(I))
4409 if (cast<llvm::CallBase>(I).doesNotThrow())
4417 Builder.SetInsertPoint(&BB, BI);
4418 emitReadHazard(Builder);
4425 if (llvm::Value *Ptr =
V.getBasePointer())
4429void FragileHazards::collectLocals() {
4431 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
4437 llvm::BasicBlock &Entry = CGF.
CurFn->getEntryBlock();
4438 for (llvm::BasicBlock::iterator
4439 I = Entry.begin(),
E = Entry.end(); I !=
E; ++I)
4440 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
4441 Locals.push_back(&*I);
4444llvm::FunctionType *FragileHazards::GetAsmFnType() {
4446 for (
unsigned i = 0, e = Locals.size(); i != e; ++i)
4447 tys[i] = Locals[i]->getType();
4448 return llvm::FunctionType::get(CGF.
VoidTy, tys,
false);
4561 bool isTry = isa<ObjCAtTryStmt>(S);
4565 CodeGenFunction::JumpDest FinallyEnd =
4570 CodeGenFunction::JumpDest FinallyRethrow =
4580 llvm::Value *SyncArg =
4581 CGF.
EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
4582 SyncArg = CGF.
Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
4594 "exceptiondata.ptr");
4600 FragileHazards Hazards(CGF);
4629 ExceptionData.emitRawPointer(CGF));
4632 llvm::Constant *
Zero = llvm::ConstantInt::get(CGF.
Builder.getInt32Ty(), 0);
4635 ObjCTypes.ExceptionDataTy, ExceptionData.emitRawPointer(CGF), GEPIndexes,
4638 ObjCTypes.getSetJmpFn(), SetJmpBuffer,
"setjmp_result");
4639 SetJmpResult->setCanReturnTwice();
4645 llvm::Value *DidCatch =
4646 CGF.
Builder.CreateIsNotNull(SetJmpResult,
"did_catch_exception");
4647 CGF.
Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
4652 CGF.
EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
4653 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
4655 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.
Builder.saveAndClearIP();
4661 Hazards.emitWriteHazard();
4665 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
4675 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF),
4686 llvm::BasicBlock *CatchBlock =
nullptr;
4687 llvm::BasicBlock *CatchHandler =
nullptr;
4693 "propagating_exception");
4699 ExceptionData.emitRawPointer(CGF));
4701 llvm::CallInst *SetJmpResult =
4703 SetJmpBuffer,
"setjmp.result");
4704 SetJmpResult->setCanReturnTwice();
4706 llvm::Value *Threw =
4707 CGF.
Builder.CreateIsNotNull(SetJmpResult,
"did_catch_exception");
4711 CGF.
Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
4721 bool AllMatched =
false;
4723 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
4742 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4749 EmitInitOfCatchParam(CGF, Caught, CatchParam);
4752 CGF.
EmitStmt(CatchStmt->getCatchBody());
4755 CatchVarCleanups.ForceCleanup();
4761 assert(OPT &&
"Unexpected non-object pointer type in @catch");
4766 assert(IDecl &&
"Catch parameter must have Objective-C type!");
4769 llvm::Value *
Class = EmitClassRef(CGF, IDecl);
4771 llvm::Value *matchArgs[] = {
Class, Caught };
4772 llvm::CallInst *Match =
4774 matchArgs,
"match");
4779 CGF.
Builder.CreateCondBr(CGF.
Builder.CreateIsNotNull(Match,
"matched"),
4780 MatchedBlock, NextCatchBlock);
4787 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
4794 CGF.
Builder.CreateBitCast(Caught,
4796 EmitInitOfCatchParam(CGF, Tmp, CatchParam);
4798 CGF.
EmitStmt(CatchStmt->getCatchBody());
4801 CatchVarCleanups.ForceCleanup();
4812 if (Caught->use_empty())
4813 Caught->eraseFromParent();
4829 assert(PropagatingExnVar.
isValid());
4831 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF),
4842 Hazards.emitHazardsInNewBlocks();
4845 CGF.
Builder.restoreIP(TryFallthroughIP);
4849 CGF.
EmitBlock(FinallyEnd.getBlock(),
true);
4852 CGBuilderTy::InsertPoint SavedIP = CGF.
Builder.saveAndClearIP();
4853 CGF.
EmitBlock(FinallyRethrow.getBlock(),
true);
4856 llvm::Value *PropagatingExn;
4857 if (PropagatingExnVar.
isValid()) {
4863 ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF));
4864 PropagatingExn = Caught;
4869 CGF.
Builder.CreateUnreachable();
4872 CGF.
Builder.restoreIP(SavedIP);
4877 bool ClearInsertionPoint) {
4878 llvm::Value *ExceptionAsObject;
4880 if (
const Expr *ThrowExpr = S.getThrowExpr()) {
4883 CGF.
Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
4886 "Unexpected rethrow outside @catch block.");
4890 CGF.
EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
4891 ->setDoesNotReturn();
4892 CGF.
Builder.CreateUnreachable();
4895 if (ClearInsertionPoint)
4896 CGF.
Builder.ClearInsertionPoint();
4905 llvm::Value *AddrWeakObjVal = CGF.
Builder.CreateBitCast(
4907 llvm::Value *read_weak =
4909 AddrWeakObjVal,
"weakread");
4910 read_weak = CGF.
Builder.CreateBitCast(read_weak, DestTy);
4918 llvm::Value *src,
Address dst) {
4919 llvm::Type * SrcTy = src->getType();
4920 if (!isa<llvm::PointerType>(SrcTy)) {
4922 assert(Size <= 8 && "does not support size > 8
");
4923 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4924 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4925 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4927 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4928 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4929 ObjCTypes.PtrObjectPtrTy);
4930 llvm::Value *args[] = { src, dstVal };
4931 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(),
4932 args, "weakassign
");
4938void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
4939 llvm::Value *src, Address dst,
4941 llvm::Type * SrcTy = src->getType();
4942 if (!isa<llvm::PointerType>(SrcTy)) {
4943 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4944 assert(Size <= 8 && "does
not support size > 8
");
4945 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4946 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4947 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4949 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4950 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4951 ObjCTypes.PtrObjectPtrTy);
4952 llvm::Value *args[] = {src, dstVal};
4954 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(),
4955 args, "globalassign
");
4957 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(),
4958 args, "threadlocalassign
");
4964void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
4965 llvm::Value *src, Address dst,
4966 llvm::Value *ivarOffset) {
4967 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is
NULL");
4968 llvm::Type * SrcTy = src->getType();
4969 if (!isa<llvm::PointerType>(SrcTy)) {
4970 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4971 assert(Size <= 8 && "does
not support size > 8
");
4972 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4973 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4974 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4976 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4977 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4978 ObjCTypes.PtrObjectPtrTy);
4979 llvm::Value *args[] = {src, dstVal, ivarOffset};
4980 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
4986void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
4987 llvm::Value *src, Address dst) {
4988 llvm::Type * SrcTy = src->getType();
4989 if (!isa<llvm::PointerType>(SrcTy)) {
4990 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
4991 assert(Size <= 8 && "does
not support size > 8
");
4992 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
4993 : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
4994 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4996 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4997 llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
4998 ObjCTypes.PtrObjectPtrTy);
4999 llvm::Value *args[] = {src, dstVal};
5000 CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(),
5001 args, "strongassign
");
5004void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
5005 Address DestPtr, Address SrcPtr,
5006 llvm::Value *size) {
5007 llvm::Value *args[] = {DestPtr.emitRawPointer(CGF),
5008 SrcPtr.emitRawPointer(CGF), size};
5009 CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
5014LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
5016 llvm::Value *BaseValue,
5017 const ObjCIvarDecl *Ivar,
5018 unsigned CVRQualifiers) {
5019 const ObjCInterfaceDecl *ID =
5020 ObjectTy->castAs<ObjCObjectType>()->getInterface();
5021 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5022 EmitIvarOffset(CGF, ID, Ivar));
5025llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
5026 const ObjCInterfaceDecl *Interface,
5027 const ObjCIvarDecl *Ivar) {
5028 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
5029 return llvm::ConstantInt::get(
5030 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
5034/* *** Private Interface *** */
5036std::string CGObjCCommonMac::GetSectionName(StringRef Section,
5037 StringRef MachOAttributes) {
5038 switch (CGM.getTriple().getObjectFormat()) {
5039 case llvm::Triple::UnknownObjectFormat:
5040 llvm_unreachable("unexpected
object file format
");
5041 case llvm::Triple::MachO: {
5042 if (MachOAttributes.empty())
5043 return ("__DATA,
" + Section).str();
5044 return ("__DATA,
" + Section + ",
" + MachOAttributes).str();
5046 case llvm::Triple::ELF:
5047 assert(Section.starts_with("__
") && "expected the name to begin with __
");
5048 return Section.substr(2).str();
5049 case llvm::Triple::COFF:
5050 assert(Section.starts_with("__
") && "expected the name to begin with __
");
5051 return (".
" + Section.substr(2) + "$B
").str();
5052 case llvm::Triple::Wasm:
5053 case llvm::Triple::GOFF:
5054 case llvm::Triple::SPIRV:
5055 case llvm::Triple::XCOFF:
5056 case llvm::Triple::DXContainer:
5057 llvm::report_fatal_error(
5058 "Objective-
C support is unimplemented
for object file format
");
5061 llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType
enum");
5072enum ImageInfoFlags {
5073 eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang.
5074 eImageInfo_GarbageCollected = (1 << 1),
5075 eImageInfo_GCOnly = (1 << 2),
5076 eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache.
5078 // A flag indicating that the module has no instances of a @synthesize of a
5079 // superclass variable. This flag used to be consumed by the runtime to work
5080 // around miscompile by gcc.
5081 eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang.
5082 eImageInfo_ImageIsSimulated = (1 << 5),
5083 eImageInfo_ClassProperties = (1 << 6)
5086void CGObjCCommonMac::EmitImageInfo() {
5087 unsigned version = 0; // Version is unused?
5088 std::string Section =
5090 ? "__OBJC,__image_info,regular
"
5091 : GetSectionName("__objc_imageinfo
", "regular,no_dead_strip
");
5093 // Generate module-level named metadata to convey this information to the
5094 // linker and code-gen.
5095 llvm::Module &Mod = CGM.getModule();
5097 // Add the ObjC ABI version to the module flags.
5098 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Version
", ObjCABI);
5099 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Image Info Version
",
5101 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Image Info Section
",
5102 llvm::MDString::get(VMContext, Section));
5104 auto Int8Ty = llvm::Type::getInt8Ty(VMContext);
5105 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
5106 // Non-GC overrides those files which specify GC.
5107 Mod.addModuleFlag(llvm::Module::Error,
5108 "Objective-
C Garbage Collection
",
5109 llvm::ConstantInt::get(Int8Ty,0));
5111 // Add the ObjC garbage collection value.
5112 Mod.addModuleFlag(llvm::Module::Error,
5113 "Objective-
C Garbage Collection
",
5114 llvm::ConstantInt::get(Int8Ty,
5115 (uint8_t)eImageInfo_GarbageCollected));
5117 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
5118 // Add the ObjC GC Only value.
5119 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C GC Only
",
5122 // Require that GC be specified and set to eImageInfo_GarbageCollected.
5123 llvm::Metadata *Ops[2] = {
5124 llvm::MDString::get(VMContext, "Objective-
C Garbage Collection
"),
5125 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
5126 Int8Ty, eImageInfo_GarbageCollected))};
5127 Mod.addModuleFlag(llvm::Module::Require, "Objective-
C GC Only
",
5128 llvm::MDNode::get(VMContext, Ops));
5132 // Indicate whether we're compiling this to run on a simulator.
5133 if (CGM.getTarget().getTriple().isSimulatorEnvironment())
5134 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Is Simulated
",
5135 eImageInfo_ImageIsSimulated);
5137 // Indicate whether we are generating class properties.
5138 Mod.addModuleFlag(llvm::Module::Error, "Objective-
C Class Properties
",
5139 eImageInfo_ClassProperties);
5142// struct objc_module {
5143// unsigned long version;
5144// unsigned long size;
5149// FIXME: Get from somewhere
5150static const int ModuleVersion = 7;
5152void CGObjCMac::EmitModuleInfo() {
5153 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
5155 ConstantInitBuilder builder(CGM);
5156 auto values = builder.beginStruct(ObjCTypes.ModuleTy);
5157 values.addInt(ObjCTypes.LongTy, ModuleVersion);
5158 values.addInt(ObjCTypes.LongTy, Size);
5159 // This used to be the filename, now it is unused. <rdr://4327263>
5160 values.add(GetClassName(StringRef("")));
5161 values.add(EmitModuleSymbols());
5162 CreateMetadataVar("OBJC_MODULES
", values,
5163 "__OBJC,__module_info,regular,no_dead_strip
",
5164 CGM.getPointerAlign(), true);
5167llvm::Constant *CGObjCMac::EmitModuleSymbols() {
5168 unsigned NumClasses = DefinedClasses.size();
5169 unsigned NumCategories = DefinedCategories.size();
5171 // Return null if no symbols were defined.
5172 if (!NumClasses && !NumCategories)
5173 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
5175 ConstantInitBuilder builder(CGM);
5176 auto values = builder.beginStruct();
5177 values.addInt(ObjCTypes.LongTy, 0);
5178 values.addNullPointer(ObjCTypes.SelectorPtrTy);
5179 values.addInt(ObjCTypes.ShortTy, NumClasses);
5180 values.addInt(ObjCTypes.ShortTy, NumCategories);
5182 // The runtime expects exactly the list of defined classes followed
5183 // by the list of defined categories, in a single array.
5184 auto array = values.beginArray(ObjCTypes.Int8PtrTy);
5185 for (unsigned i=0; i<NumClasses; i++) {
5186 const ObjCInterfaceDecl *ID = ImplementedClasses[i];
5188 if (ObjCImplementationDecl *IMP = ID->getImplementation())
5189 // We are implementing a weak imported interface. Give it external linkage
5190 if (ID->isWeakImported() && !IMP->isWeakImported())
5191 DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
5193 array.add(DefinedClasses[i]);
5195 for (unsigned i=0; i<NumCategories; i++)
5196 array.add(DefinedCategories[i]);
5198 array.finishAndAddTo(values);
5200 llvm::GlobalVariable *GV = CreateMetadataVar(
5201 "OBJC_SYMBOLS
", values, "__OBJC,__symbols,regular,no_dead_strip
",
5202 CGM.getPointerAlign(), true);
5206llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
5207 IdentifierInfo *II) {
5208 LazySymbols.insert(II);
5210 llvm::GlobalVariable *&Entry = ClassReferences[II];
5214 CreateMetadataVar("OBJC_CLASS_REFERENCES_
", GetClassName(II->getName()),
5215 "__OBJC,__cls_refs,literal_pointers,no_dead_strip
",
5216 CGM.getPointerAlign(), true);
5219 return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry,
5220 CGF.getPointerAlign());
5223llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
5224 const ObjCInterfaceDecl *ID) {
5225 // If the class has the objc_runtime_visible attribute, we need to
5226 // use the Objective-C runtime to get the class.
5227 if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
5228 return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
5230 IdentifierInfo *RuntimeName =
5231 &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
5232 return EmitClassRefFromId(CGF, RuntimeName);
5235llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
5236 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool
");
5237 return EmitClassRefFromId(CGF, II);
5240llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
5241 return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel));
5244ConstantAddress CGObjCMac::EmitSelectorAddr(Selector Sel) {
5245 CharUnits Align = CGM.getPointerAlign();
5247 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
5249 Entry = CreateMetadataVar(
5250 "OBJC_SELECTOR_REFERENCES_
", GetMethodVarName(Sel),
5251 "__OBJC,__message_refs,literal_pointers,no_dead_strip
", Align, true);
5252 Entry->setExternallyInitialized(true);
5255 return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align);
5258llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
5259 llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
5261 Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
5262 return getConstantGEP(VMContext, Entry, 0, 0);
5265llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
5266 return MethodDefinitions.lookup(MD);
5271llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
5272 const ObjCCommonTypesHelper &ObjCTypes) {
5273 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
5276void IvarLayoutBuilder::visitRecord(const RecordType *RT,
5278 const RecordDecl *RD = RT->getDecl();
5280 // If this is a union, remember that we had one, because it might mess
5281 // up the ordering of layout entries.
5283 IsDisordered = true;
5285 const ASTRecordLayout *recLayout = nullptr;
5286 visitAggregate(RD->field_begin(), RD->field_end(), offset,
5287 [&](const FieldDecl *field) -> CharUnits {
5289 recLayout = &CGM.getContext().getASTRecordLayout(RD);
5290 auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex());
5291 return CGM.getContext().toCharUnitsFromBits(offsetInBits);
5295template <class Iterator, class GetOffsetFn>
5296void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
5297 CharUnits aggregateOffset,
5298 const GetOffsetFn &getOffset) {
5299 for (; begin != end; ++begin) {
5300 auto field = *begin;
5302 // Skip over bitfields.
5303 if (field->isBitField()) {
5307 // Compute the offset of the field within the aggregate.
5308 CharUnits fieldOffset = aggregateOffset + getOffset(field);
5310 visitField(field, fieldOffset);
5315void IvarLayoutBuilder::visitField(const FieldDecl *field,
5316 CharUnits fieldOffset) {
5317 QualType fieldType = field->getType();
5319 // Drill down into arrays.
5320 uint64_t numElts = 1;
5321 if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) {
5323 fieldType = arrayType->getElementType();
5325 // Unlike incomplete arrays, constant arrays can be nested.
5326 while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
5327 numElts *= arrayType->getZExtSize();
5328 fieldType = arrayType->getElementType();
5331 assert(!fieldType->isArrayType() && "ivar of non-constant array
type?
");
5333 // If we ended up with a zero-sized array, we've done what we can do within
5334 // the limits of this layout encoding.
5335 if (numElts == 0) return;
5337 // Recurse if the base element type is a record type.
5338 if (auto recType = fieldType->getAs<RecordType>()) {
5339 size_t oldEnd = IvarsInfo.size();
5341 visitRecord(recType, fieldOffset);
5343 // If we have an array, replicate the first entry's layout information.
5344 auto numEltEntries = IvarsInfo.size() - oldEnd;
5345 if (numElts != 1 && numEltEntries != 0) {
5346 CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
5347 for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
5348 // Copy the last numEltEntries onto the end of the array, adjusting
5349 // each for the element size.
5350 for (size_t i = 0; i != numEltEntries; ++i) {
5351 auto firstEntry = IvarsInfo[oldEnd + i];
5352 IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
5353 firstEntry.SizeInWords));
5361 // Classify the element type.
5362 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);
5364 // If it matches what we're looking for, add an entry.
5365 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
5366 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
5367 assert(CGM.getContext().getTypeSizeInChars(fieldType)
5368 == CGM.getPointerSize());
5369 IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
5376llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
5377 llvm::SmallVectorImpl<unsigned char> &buffer) {
5378 // The bitmap is a series of skip/scan instructions, aligned to word
5379 // boundaries. The skip is performed first.
5380 const unsigned char MaxNibble = 0xF;
5381 const unsigned char SkipMask = 0xF0, SkipShift = 4;
5382 const unsigned char ScanMask = 0x0F, ScanShift = 0;
5384 assert(!IvarsInfo.empty() && "generating bitmap
for no data
");
5386 // Sort the ivar info on byte position in case we encounterred a
5387 // union nested in the ivar list.
5389 // This isn't a stable sort, but our algorithm should handle it fine.
5390 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
5392 assert(llvm::is_sorted(IvarsInfo));
5394 assert(IvarsInfo.back().Offset < InstanceEnd);
5396 assert(buffer.empty());
5398 // Skip the next N words.
5399 auto skip = [&](unsigned numWords) {
5400 assert(numWords > 0);
5402 // Try to merge into the previous byte. Since scans happen second, we
5403 // can't do this if it includes a scan.
5404 if (!buffer.empty() && !(buffer.back() & ScanMask)) {
5405 unsigned lastSkip = buffer.back() >> SkipShift;
5406 if (lastSkip < MaxNibble) {
5407 unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
5408 numWords -= claimed;
5409 lastSkip += claimed;
5410 buffer.back() = (lastSkip << SkipShift);
5414 while (numWords >= MaxNibble) {
5415 buffer.push_back(MaxNibble << SkipShift);
5416 numWords -= MaxNibble;
5419 buffer.push_back(numWords << SkipShift);
5423 // Scan the next N words.
5424 auto scan = [&](unsigned numWords) {
5425 assert(numWords > 0);
5427 // Try to merge into the previous byte. Since scans happen second, we can
5428 // do this even if it includes a skip.
5429 if (!buffer.empty()) {
5430 unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
5431 if (lastScan < MaxNibble) {
5432 unsigned claimed = std::min(MaxNibble - lastScan, numWords);
5433 numWords -= claimed;
5434 lastScan += claimed;
5435 buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
5439 while (numWords >= MaxNibble) {
5440 buffer.push_back(MaxNibble << ScanShift);
5441 numWords -= MaxNibble;
5444 buffer.push_back(numWords << ScanShift);
5448 // One past the end of the last scan.
5449 unsigned endOfLastScanInWords = 0;
5450 const CharUnits WordSize = CGM.getPointerSize();
5452 // Consider all the scan requests.
5453 for (auto &request : IvarsInfo) {
5454 CharUnits beginOfScan = request.Offset - InstanceBegin;
5456 // Ignore scan requests that don't start at an even multiple of the
5457 // word size. We can't encode them.
5458 if ((beginOfScan % WordSize) != 0) continue;
5460 // Ignore scan requests that start before the instance start.
5461 // This assumes that scans never span that boundary. The boundary
5462 // isn't the true start of the ivars, because in the fragile-ARC case
5463 // it's rounded up to word alignment, but the test above should leave
5464 // us ignoring that possibility.
5465 if (beginOfScan.isNegative()) {
5466 assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
5470 unsigned beginOfScanInWords = beginOfScan / WordSize;
5471 unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;
5473 // If the scan starts some number of words after the last one ended,
5475 if (beginOfScanInWords > endOfLastScanInWords) {
5476 skip(beginOfScanInWords - endOfLastScanInWords);
5478 // Otherwise, start scanning where the last left off.
5480 beginOfScanInWords = endOfLastScanInWords;
5482 // If that leaves us with nothing to scan, ignore this request.
5483 if (beginOfScanInWords >= endOfScanInWords) continue;
5486 // Scan to the end of the request.
5487 assert(beginOfScanInWords < endOfScanInWords);
5488 scan(endOfScanInWords - beginOfScanInWords);
5489 endOfLastScanInWords = endOfScanInWords;
5493 return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
5495 // For GC layouts, emit a skip to the end of the allocation so that we
5496 // have precise information about the entire thing. This isn't useful
5497 // or necessary for the ARC-style layout strings.
5498 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
5499 unsigned lastOffsetInWords =
5500 (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
5501 if (lastOffsetInWords > endOfLastScanInWords) {
5502 skip(lastOffsetInWords - endOfLastScanInWords);
5506 // Null terminate the string.
5507 buffer.push_back(0);
5509 auto *Entry = CGObjC.CreateCStringLiteral(
5510 reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName);
5511 return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
5531CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
5532 CharUnits beginOffset, CharUnits endOffset,
5533 bool ForStrongLayout, bool HasMRCWeakIvars) {
5534 // If this is MRC, and we're either building a strong layout or there
5535 // are no weak ivars, bail out early.
5536 llvm::Type *PtrTy = CGM.Int8PtrTy;
5537 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
5538 !CGM.getLangOpts().ObjCAutoRefCount &&
5539 (ForStrongLayout || !HasMRCWeakIvars))
5540 return llvm::Constant::getNullValue(PtrTy);
5542 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
5543 SmallVector<const ObjCIvarDecl*, 32> ivars;
5545 // GC layout strings include the complete object layout, possibly
5546 // inaccurately in the non-fragile ABI; the runtime knows how to fix this
5549 // ARC layout strings only include the class's ivars. In non-fragile
5550 // runtimes, that means starting at InstanceStart, rounded up to word
5551 // alignment. In fragile runtimes, there's no InstanceStart, so it means
5552 // starting at the offset of the first ivar, rounded up to word alignment.
5554 // MRC weak layout strings follow the ARC style.
5555 CharUnits baseOffset;
5556 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
5557 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
5558 IVD; IVD = IVD->getNextIvar())
5559 ivars.push_back(IVD);
5561 if (isNonFragileABI()) {
5562 baseOffset = beginOffset; // InstanceStart
5563 } else if (!ivars.empty()) {
5565 CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
5567 baseOffset = CharUnits::Zero();
5570 baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
5573 CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);
5575 baseOffset = CharUnits::Zero();
5579 return llvm::Constant::getNullValue(PtrTy);
5581 IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);
5583 builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
5584 [&](const ObjCIvarDecl *ivar) -> CharUnits {
5585 return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar));
5588 if (!builder.hasBitmapData())
5589 return llvm::Constant::getNullValue(PtrTy);
5591 llvm::SmallVector<unsigned char, 4> buffer;
5592 llvm::Constant *C = builder.buildBitmap(*this, buffer);
5594 if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
5595 printf("\n%
s ivar layout
for class '%s':
",
5596 ForStrongLayout ? "strong
" : "weak
",
5597 OMD->getClassInterface()->getName().str().c_str());
5598 builder.dump(buffer);
5603llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
5604 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
5605 // FIXME: Avoid std::string in "Sel.
getAsString()
"
5607 Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
5608 return getConstantGEP(VMContext, Entry, 0, 0);
5611// FIXME: Merge into a single cstring creation function.
5612llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
5613 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
5616llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
5617 std::string TypeStr;
5618 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
5620 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
5622 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
5623 return getConstantGEP(VMContext, Entry, 0, 0);
5626llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
5628 std::string TypeStr =
5629 CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);
5631 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
5633 Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
5634 return getConstantGEP(VMContext, Entry, 0, 0);
5637// FIXME: Merge into a single cstring creation function.
5638llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
5639 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
5641 Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
5642 return getConstantGEP(VMContext, Entry, 0, 0);
5645// FIXME: Merge into a single cstring creation function.
5646// FIXME: This Decl should be more precise.
5648CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
5649 const Decl *Container) {
5650 std::string TypeStr =
5651 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
5652 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
5655void CGObjCMac::FinishModule() {
5658 // Emit the dummy bodies for any protocols which were referenced but
5660 for (auto &entry : Protocols) {
5661 llvm::GlobalVariable *global = entry.second;
5662 if (global->hasInitializer())
5665 ConstantInitBuilder builder(CGM);
5666 auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
5667 values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
5668 values.add(GetClassName(entry.first->getName()));
5669 values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
5670 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5671 values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
5672 values.finishAndSetAsInitializer(global);
5673 CGM.addCompilerUsedGlobal(global);
5676 // Add assembler directives to add lazy undefined symbol references
5677 // for classes which are referenced but not defined. This is
5678 // important for correct linker interaction.
5680 // FIXME: It would be nice if we had an LLVM construct for this.
5681 if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
5682 CGM.getTriple().isOSBinFormatMachO()) {
5683 SmallString<256> Asm;
5684 Asm += CGM.getModule().getModuleInlineAsm();
5685 if (!Asm.empty() && Asm.back() != '\n')
5688 llvm::raw_svector_ostream OS(Asm);
5689 for (const auto *Sym : DefinedSymbols)
5690 OS << "\t.objc_class_name_
" << Sym->getName() << "=0\n
"
5691 << "\t.globl .objc_class_name_
" << Sym->getName() << "\n
";
5692 for (const auto *Sym : LazySymbols)
5693 OS << "\t.lazy_reference .objc_class_name_
" << Sym->getName() << "\n
";
5694 for (const auto &Category : DefinedCategoryNames)
5695 OS << "\t.objc_category_name_
" << Category << "=0\n
"
5696 << "\t.globl .objc_category_name_
" << Category << "\n
";
5698 CGM.getModule().setModuleInlineAsm(OS.str());
5702CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
5703 : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
5704 ObjCEmptyVtableVar(nullptr) {
5710ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
5711 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr)
5713 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5714 ASTContext &Ctx = CGM.getContext();
5715 unsigned ProgramAS = CGM.getDataLayout().getProgramAddressSpace();
5717 ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
5719 LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
5720 Int8PtrTy = CGM.Int8PtrTy;
5721 Int8PtrProgramASTy = llvm::PointerType::get(CGM.Int8Ty, ProgramAS);
5722 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
5724 // arm64 targets use "int" ivar offset variables. All others,
5725 // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
5726 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
5727 IvarOffsetVarTy = IntTy;
5729 IvarOffsetVarTy = LongTy;
5732 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
5734 llvm::PointerType::getUnqual(ObjectPtrTy);
5736 cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));
5738 // I'm not sure I like this. The implicit coordination is a bit
5739 // gross. We should solve this in a reasonable fashion because this
5740 // is a pretty common task (match some runtime data structure with
5741 // an LLVM data structure).
5743 // FIXME: This is leaked.
5744 // FIXME: Merge with rewriter code?
5746 // struct _objc_super {
5750 RecordDecl *RD = RecordDecl::Create(
5751 Ctx, TagTypeKind::Struct, Ctx.getTranslationUnitDecl(), SourceLocation(),
5752 SourceLocation(), &Ctx.Idents.get("_objc_super
"));
5753 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5754 nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
5755 false, ICIS_NoInit));
5756 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
5757 nullptr, Ctx.getObjCClassType(), nullptr,
5758 nullptr, false, ICIS_NoInit));
5759 RD->completeDefinition();
5761 SuperCTy = Ctx.getTagDeclType(RD);
5762 SuperPtrCTy = Ctx.getPointerType(SuperCTy);