31#include "llvm/ADT/SmallVector.h"
32#include "llvm/ADT/StringMap.h"
33#include "llvm/IR/DataLayout.h"
34#include "llvm/IR/Intrinsics.h"
35#include "llvm/IR/LLVMContext.h"
36#include "llvm/IR/Module.h"
37#include "llvm/Support/Compiler.h"
38#include "llvm/Support/ConvertUTF.h"
49class LazyRuntimeFunction {
50 CodeGenModule *CGM =
nullptr;
51 llvm::FunctionType *FTy =
nullptr;
52 const char *FunctionName =
nullptr;
53 llvm::FunctionCallee Function =
nullptr;
56 LazyRuntimeFunction() =
default;
60 template <
typename... Tys>
61 void init(CodeGenModule *Mod,
const char *name, llvm::Type *RetTy,
67 SmallVector<llvm::Type *, 8> ArgTys({Types...});
68 FTy = llvm::FunctionType::get(RetTy, ArgTys,
false);
71 FTy = llvm::FunctionType::get(RetTy, {},
false);
75 llvm::FunctionType *
getType() {
return FTy; }
79 operator llvm::FunctionCallee() {
83 Function = CGM->CreateRuntimeFunction(FTy, FunctionName);
96 llvm::Module &TheModule;
99 llvm::StructType *ObjCSuperTy;
102 llvm::PointerType *PtrToObjCSuperTy;
106 llvm::PointerType *SelectorTy;
108 llvm::Type *SelectorElemTy;
111 llvm::IntegerType *Int8Ty;
114 llvm::PointerType *PtrToInt8Ty;
116 llvm::StructType *ProtocolTy;
118 llvm::PointerType *ProtocolPtrTy;
124 llvm::PointerType *IMPTy;
129 llvm::PointerType *IdTy;
131 llvm::Type *IdElemTy;
134 llvm::PointerType *PtrToIdTy;
139 llvm::IntegerType *IntTy;
143 llvm::PointerType *PtrTy;
147 llvm::IntegerType *LongTy;
149 llvm::IntegerType *SizeTy;
151 llvm::IntegerType *IntPtrTy;
153 llvm::IntegerType *PtrDiffTy;
156 llvm::PointerType *PtrToIntTy;
160 llvm::IntegerType *Int32Ty;
162 llvm::IntegerType *Int64Ty;
164 llvm::StructType *PropertyMetadataTy;
168 unsigned msgSendMDKind;
171 bool usesSEHExceptions;
173 bool usesCxxExceptions;
178 return (
R.getKind() ==
kind) &&
179 (
R.getVersion() >= VersionTuple(major, minor));
182 std::string ManglePublicSymbol(StringRef Name) {
183 return (StringRef(CGM.
getTriple().isOSBinFormatCOFF() ?
"$_" :
"._") + Name).str();
186 std::string SymbolForProtocol(Twine Name) {
187 return (ManglePublicSymbol(
"OBJC_PROTOCOL_") + Name).str();
190 std::string SymbolForProtocolRef(StringRef Name) {
191 return (ManglePublicSymbol(
"OBJC_REF_PROTOCOL_") + Name).str();
198 llvm::Constant *MakeConstantString(StringRef Str, StringRef Name =
"") {
199 ConstantAddress
Array =
208 llvm::Constant *ExportUniqueString(
const std::string &Str,
209 const std::string &prefix,
211 std::string
name = prefix + Str;
212 auto *ConstStr = TheModule.getGlobalVariable(name);
214 llvm::Constant *value = llvm::ConstantDataArray::getString(VMContext,Str);
215 auto *GV =
new llvm::GlobalVariable(TheModule, value->getType(),
true,
216 llvm::GlobalValue::LinkOnceODRLinkage, value, name);
217 GV->setComdat(TheModule.getOrInsertComdat(name));
219 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
226 llvm::Constant *MakePropertyEncodingString(
const ObjCPropertyDecl *PD,
227 const Decl *Container) {
230 std::string NameAndAttributes;
231 std::string TypeStr =
233 NameAndAttributes +=
'\0';
234 NameAndAttributes += TypeStr.length() + 3;
235 NameAndAttributes += TypeStr;
236 NameAndAttributes +=
'\0';
238 return MakeConstantString(NameAndAttributes);
244 void PushPropertyAttributes(ConstantStructBuilder &Fields,
245 const ObjCPropertyDecl *property,
bool isSynthesized=
true,
bool
247 int attrs =
property->getPropertyAttributes();
250 attrs &= ~ObjCPropertyAttribute::kind_copy;
251 attrs &= ~ObjCPropertyAttribute::kind_retain;
252 attrs &= ~ObjCPropertyAttribute::kind_weak;
253 attrs &= ~ObjCPropertyAttribute::kind_strong;
256 Fields.
addInt(Int8Ty, attrs & 0xff);
262 attrs |= isSynthesized ? (1<<0) : 0;
263 attrs |= isDynamic ? (1<<1) : 0;
266 Fields.
addInt(Int8Ty, attrs & 0xff);
272 virtual llvm::Constant *GenerateCategoryProtocolList(
const
273 ObjCCategoryDecl *OCD);
274 virtual ConstantArrayBuilder PushPropertyListHeader(ConstantStructBuilder &Fields,
277 Fields.
addInt(IntTy, count);
280 const llvm::DataLayout &DL = TheModule.getDataLayout();
281 Fields.
addInt(IntTy, DL.getTypeSizeInBits(PropertyMetadataTy) /
289 virtual void PushProperty(ConstantArrayBuilder &PropertiesArray,
290 const ObjCPropertyDecl *property,
292 bool isSynthesized=
true,
bool
294 auto Fields = PropertiesArray.
beginStruct(PropertyMetadataTy);
296 Fields.
add(MakePropertyEncodingString(property, OCD));
297 PushPropertyAttributes(Fields, property, isSynthesized, isDynamic);
298 auto addPropertyMethod = [&](
const ObjCMethodDecl *accessor) {
301 llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
302 Fields.
add(MakeConstantString(accessor->getSelector().getAsString()));
303 Fields.
add(TypeEncoding);
317 llvm::Value *EnforceType(CGBuilderTy &B, llvm::Value *
V, llvm::Type *Ty) {
318 if (
V->getType() == Ty)
320 return B.CreateBitCast(
V, Ty);
324 llvm::Constant *Zeros[2];
326 llvm::Constant *NULLPtr;
328 llvm::LLVMContext &VMContext;
336 llvm::GlobalAlias *ClassPtrAlias;
341 llvm::GlobalAlias *MetaClassPtrAlias;
343 std::vector<llvm::Constant*> Classes;
345 std::vector<llvm::Constant*> Categories;
348 std::vector<llvm::Constant*> ConstantStrings;
352 llvm::StringMap<llvm::Constant*> ObjCStrings;
354 llvm::StringMap<llvm::Constant*> ExistingProtocols;
360 typedef std::pair<std::string, llvm::GlobalAlias*> TypedSelector;
364 typedef llvm::DenseMap<Selector, SmallVector<TypedSelector, 2> >
368 SelectorMap SelectorTable;
372 Selector RetainSel, ReleaseSel, AutoreleaseSel;
376 LazyRuntimeFunction IvarAssignFn, StrongCastAssignFn, MemMoveFn, WeakReadFn,
377 WeakAssignFn, GlobalAssignFn;
379 typedef std::pair<std::string, std::string> ClassAliasPair;
381 std::vector<ClassAliasPair> ClassAliases;
385 LazyRuntimeFunction ExceptionThrowFn;
388 LazyRuntimeFunction ExceptionReThrowFn;
391 LazyRuntimeFunction EnterCatchFn;
394 LazyRuntimeFunction ExitCatchFn;
396 LazyRuntimeFunction SyncEnterFn;
398 LazyRuntimeFunction SyncExitFn;
403 LazyRuntimeFunction EnumerationMutationFn;
406 LazyRuntimeFunction GetPropertyFn;
409 LazyRuntimeFunction SetPropertyFn;
411 LazyRuntimeFunction GetStructPropertyFn;
413 LazyRuntimeFunction SetStructPropertyFn;
425 const int ProtocolVersion;
428 const int ClassABIVersion;
433 virtual llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
434 ArrayRef<llvm::Constant *> IvarTypes,
435 ArrayRef<llvm::Constant *> IvarOffsets,
436 ArrayRef<llvm::Constant *> IvarAlign,
437 ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership);
444 llvm::Constant *GenerateMethodList(StringRef ClassName,
445 StringRef CategoryName,
446 ArrayRef<const ObjCMethodDecl*> Methods,
447 bool isClassMethodList);
452 virtual llvm::Constant *GenerateEmptyProtocol(StringRef ProtocolName);
456 llvm::Constant *GeneratePropertyList(
const Decl *Container,
457 const ObjCContainerDecl *OCD,
458 bool isClassProperty=
false,
459 bool protocolOptionalProperties=
false);
463 llvm::Constant *GenerateProtocolList(ArrayRef<std::string> Protocols);
469 void GenerateProtocolHolderCategory();
472 llvm::Constant *GenerateClassStructure(
473 llvm::Constant *MetaClass,
474 llvm::Constant *SuperClass,
477 llvm::Constant *Version,
478 llvm::Constant *InstanceSize,
479 llvm::Constant *IVars,
480 llvm::Constant *Methods,
481 llvm::Constant *Protocols,
482 llvm::Constant *IvarOffsets,
483 llvm::Constant *Properties,
484 llvm::Constant *StrongIvarBitmap,
485 llvm::Constant *WeakIvarBitmap,
490 virtual llvm::Constant *GenerateProtocolMethodList(
491 ArrayRef<const ObjCMethodDecl*> Methods);
494 void EmitProtocolMethodList(T &&Methods, llvm::Constant *&
Required,
496 SmallVector<const ObjCMethodDecl*, 16> RequiredMethods;
497 SmallVector<const ObjCMethodDecl*, 16> OptionalMethods;
498 for (
const auto *I : Methods)
500 OptionalMethods.push_back(I);
502 RequiredMethods.push_back(I);
503 Required = GenerateProtocolMethodList(RequiredMethods);
504 Optional = GenerateProtocolMethodList(OptionalMethods);
509 virtual llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
510 const std::string &TypeEncoding);
515 virtual std::string GetIVarOffsetVariableName(
const ObjCInterfaceDecl *ID,
516 const ObjCIvarDecl *Ivar) {
517 const std::string Name =
"__objc_ivar_offset_" +
ID->getNameAsString()
522 llvm::GlobalVariable *ObjCIvarOffsetVariable(
const ObjCInterfaceDecl *ID,
523 const ObjCIvarDecl *Ivar);
526 void EmitClassRef(
const std::string &className);
529 virtual llvm::Value *GetClassNamed(CodeGenFunction &CGF,
530 const std::string &Name,
bool isWeak);
535 virtual llvm::Value *LookupIMP(CodeGenFunction &CGF,
536 llvm::Value *&Receiver,
539 MessageSendInfo &MSI) = 0;
544 virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF,
547 MessageSendInfo &MSI) = 0;
560 llvm::Constant *MakeBitField(ArrayRef<bool> bits);
563 CGObjCGNU(CodeGenModule &cgm,
unsigned runtimeABIVersion,
564 unsigned protocolClassVersion,
unsigned classABI=1);
566 ConstantAddress GenerateConstantString(
const StringLiteral *SL)
override;
568 ConstantAddress GenerateConstantNumber(
const bool Value,
569 const QualType &Ty)
override;
570 ConstantAddress GenerateConstantNumber(
const llvm::APSInt &
Value,
571 const QualType &Ty)
override;
572 ConstantAddress GenerateConstantNumber(
const llvm::APFloat &
Value,
573 const QualType &Ty)
override;
575 GenerateConstantArray(
const ArrayRef<llvm::Constant *> &Objects)
override;
576 ConstantAddress GenerateConstantDictionary(
577 const ObjCDictionaryLiteral *E,
578 ArrayRef<std::pair<llvm::Constant *, llvm::Constant *>> KeysAndObjects)
582 GenerateMessageSend(CodeGenFunction &CGF, ReturnValueSlot Return,
583 QualType ResultType, Selector Sel,
584 llvm::Value *Receiver,
const CallArgList &CallArgs,
585 const ObjCInterfaceDecl *
Class,
586 const ObjCMethodDecl *
Method)
override;
588 GenerateMessageSendSuper(CodeGenFunction &CGF, ReturnValueSlot Return,
589 QualType ResultType, Selector Sel,
590 const ObjCInterfaceDecl *
Class,
591 bool isCategoryImpl, llvm::Value *Receiver,
592 bool IsClassMessage,
const CallArgList &CallArgs,
593 const ObjCMethodDecl *
Method)
override;
594 llvm::Value *GetClass(CodeGenFunction &CGF,
595 const ObjCInterfaceDecl *OID)
override;
596 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel)
override;
597 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel)
override;
598 llvm::Value *GetSelector(CodeGenFunction &CGF,
599 const ObjCMethodDecl *
Method)
override;
600 virtual llvm::Constant *GetConstantSelector(Selector Sel,
601 const std::string &TypeEncoding) {
602 llvm_unreachable(
"Runtime unable to generate constant selector");
604 llvm::Constant *GetConstantSelector(
const ObjCMethodDecl *M) {
608 llvm::Constant *GetEHType(QualType T)
override;
610 llvm::Function *GenerateMethod(
const ObjCMethodDecl *OMD,
611 const ObjCContainerDecl *CD)
override;
614 llvm::DenseMap<const ObjCMethodDecl *, llvm::Function *>
615 DirectMethodDefinitions;
616 void GenerateDirectMethodsPreconditionCheck(
617 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
618 const ObjCContainerDecl *CD)
override;
619 void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
620 const ObjCMethodDecl *OMD,
621 const ObjCContainerDecl *CD)
override;
622 void GenerateCategory(
const ObjCCategoryImplDecl *CMD)
override;
623 void GenerateClass(
const ObjCImplementationDecl *ClassDecl)
override;
624 void RegisterAlias(
const ObjCCompatibleAliasDecl *OAD)
override;
625 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
626 const ObjCProtocolDecl *PD)
override;
627 void GenerateProtocol(
const ObjCProtocolDecl *PD)
override;
629 virtual llvm::Constant *GenerateProtocolRef(
const ObjCProtocolDecl *PD);
631 llvm::Constant *GetOrEmitProtocol(
const ObjCProtocolDecl *PD)
override {
632 return GenerateProtocolRef(PD);
635 llvm::Function *ModuleInitFunction()
override;
636 llvm::FunctionCallee GetPropertyGetFunction()
override;
637 llvm::FunctionCallee GetPropertySetFunction()
override;
638 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
640 llvm::FunctionCallee GetSetStructFunction()
override;
641 llvm::FunctionCallee GetGetStructFunction()
override;
642 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override;
643 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override;
644 llvm::FunctionCallee EnumerationMutationFunction()
override;
646 void EmitTryStmt(CodeGenFunction &CGF,
647 const ObjCAtTryStmt &S)
override;
648 void EmitSynchronizedStmt(CodeGenFunction &CGF,
649 const ObjCAtSynchronizedStmt &S)
override;
650 void EmitThrowStmt(CodeGenFunction &CGF,
651 const ObjCAtThrowStmt &S,
652 bool ClearInsertionPoint=
true)
override;
653 llvm::Value * EmitObjCWeakRead(CodeGenFunction &CGF,
654 Address AddrWeakObj)
override;
655 void EmitObjCWeakAssign(CodeGenFunction &CGF,
656 llvm::Value *src, Address dst)
override;
657 void EmitObjCGlobalAssign(CodeGenFunction &CGF,
658 llvm::Value *src, Address dest,
659 bool threadlocal=
false)
override;
660 void EmitObjCIvarAssign(CodeGenFunction &CGF, llvm::Value *src,
661 Address dest, llvm::Value *ivarOffset)
override;
662 void EmitObjCStrongCastAssign(CodeGenFunction &CGF,
663 llvm::Value *src, Address dest)
override;
664 void EmitGCMemmoveCollectable(CodeGenFunction &CGF, Address DestPtr,
666 llvm::Value *Size)
override;
667 LValue EmitObjCValueForIvar(CodeGenFunction &CGF, QualType ObjectTy,
668 llvm::Value *BaseValue,
const ObjCIvarDecl *Ivar,
669 unsigned CVRQualifiers)
override;
670 llvm::Value *EmitIvarOffset(CodeGenFunction &CGF,
672 const ObjCIvarDecl *Ivar)
override;
673 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF)
override;
674 llvm::Constant *BuildGCBlockLayout(CodeGenModule &CGM,
675 const CGBlockInfo &blockInfo)
override {
678 llvm::Constant *BuildRCBlockLayout(CodeGenModule &CGM,
679 const CGBlockInfo &blockInfo)
override {
683 llvm::Constant *BuildByrefLayout(CodeGenModule &CGM, QualType T)
override {
696class CGObjCGCC :
public CGObjCGNU {
699 LazyRuntimeFunction MsgLookupFn;
703 LazyRuntimeFunction MsgLookupSuperFn;
706 llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver,
707 llvm::Value *cmd, llvm::MDNode *node,
708 MessageSendInfo &MSI)
override {
709 CGBuilderTy &Builder = CGF.
Builder;
710 llvm::Value *args[] = {
711 EnforceType(Builder, Receiver, IdTy),
712 EnforceType(Builder, cmd, SelectorTy) };
714 imp->setMetadata(msgSendMDKind, node);
718 llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
719 llvm::Value *cmd, MessageSendInfo &MSI)
override {
720 CGBuilderTy &Builder = CGF.
Builder;
721 llvm::Value *lookupArgs[] = {
722 EnforceType(Builder, ObjCSuper.
emitRawPointer(CGF), PtrToObjCSuperTy),
728 CGObjCGCC(CodeGenModule &Mod) : CGObjCGNU(Mod, 8, 2) {
730 MsgLookupFn.init(&CGM,
"objc_msg_lookup", IMPTy, IdTy, SelectorTy);
732 MsgLookupSuperFn.init(&CGM,
"objc_msg_lookup_super", IMPTy,
733 PtrToObjCSuperTy, SelectorTy);
738class CGObjCGNUstep :
public CGObjCGNU {
741 LazyRuntimeFunction SlotLookupFn;
746 LazyRuntimeFunction SlotLookupSuperFn;
748 LazyRuntimeFunction SetPropertyAtomic;
750 LazyRuntimeFunction SetPropertyAtomicCopy;
752 LazyRuntimeFunction SetPropertyNonAtomic;
754 LazyRuntimeFunction SetPropertyNonAtomicCopy;
757 LazyRuntimeFunction CxxAtomicObjectGetFn;
760 LazyRuntimeFunction CxxAtomicObjectSetFn;
765 llvm::Type *SlotStructTy;
768 llvm::Constant *GetEHType(QualType T)
override;
771 llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver,
772 llvm::Value *cmd, llvm::MDNode *node,
773 MessageSendInfo &MSI)
override {
774 CGBuilderTy &Builder = CGF.
Builder;
775 llvm::FunctionCallee LookupFn = SlotLookupFn;
778 RawAddress ReceiverPtr =
780 Builder.CreateStore(Receiver, ReceiverPtr);
787 self = llvm::ConstantPointerNull::get(IdTy);
791 if (
auto *LookupFn2 = dyn_cast<llvm::Function>(LookupFn.getCallee()))
792 LookupFn2->addParamAttr(
794 llvm::CaptureInfo::none()));
796 llvm::Value *args[] = {
797 EnforceType(Builder, ReceiverPtr.
getPointer(), PtrToIdTy),
798 EnforceType(Builder, cmd, SelectorTy),
799 EnforceType(Builder, self, IdTy)};
801 slot->setOnlyReadsMemory();
802 slot->setMetadata(msgSendMDKind, node);
805 llvm::Value *imp = Builder.CreateAlignedLoad(
806 IMPTy, Builder.CreateStructGEP(SlotStructTy, slot, 4),
811 Receiver = Builder.CreateLoad(ReceiverPtr,
true);
815 llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
817 MessageSendInfo &MSI)
override {
818 CGBuilderTy &Builder = CGF.
Builder;
821 llvm::CallInst *slot =
823 slot->setOnlyReadsMemory();
825 return Builder.CreateAlignedLoad(
826 IMPTy, Builder.CreateStructGEP(SlotStructTy, slot, 4),
831 CGObjCGNUstep(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 9, 3, 1) {}
832 CGObjCGNUstep(CodeGenModule &Mod,
unsigned ABI,
unsigned ProtocolABI,
834 CGObjCGNU(Mod, ABI, ProtocolABI, ClassABI) {
837 SlotStructTy = llvm::StructType::get(PtrTy, PtrTy, PtrTy, IntTy, IMPTy);
840 SlotLookupFn.init(&CGM,
"objc_msg_lookup_sender", SlotTy, PtrToIdTy,
843 SlotLookupSuperFn.init(&CGM,
"objc_slot_lookup_super", SlotTy,
844 PtrToObjCSuperTy, SelectorTy);
846 llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
847 if (usesCxxExceptions) {
849 EnterCatchFn.init(&CGM,
"__cxa_begin_catch", PtrTy, PtrTy);
851 ExitCatchFn.init(&CGM,
"__cxa_end_catch", VoidTy);
853 ExceptionReThrowFn.init(&CGM,
"__cxa_rethrow", PtrTy);
854 }
else if (usesSEHExceptions) {
856 ExceptionReThrowFn.init(&CGM,
"objc_exception_rethrow", VoidTy);
859 EnterCatchFn.init(&CGM,
"__cxa_begin_catch", PtrTy, PtrTy);
861 ExitCatchFn.init(&CGM,
"__cxa_end_catch", VoidTy);
863 ExceptionReThrowFn.init(&CGM,
"_Unwind_Resume_or_Rethrow", VoidTy,
865 }
else if (
R.getVersion() >= VersionTuple(1, 7)) {
867 EnterCatchFn.init(&CGM,
"objc_begin_catch", IdTy, PtrTy);
869 ExitCatchFn.init(&CGM,
"objc_end_catch", VoidTy);
871 ExceptionReThrowFn.init(&CGM,
"objc_exception_rethrow", VoidTy, PtrTy);
873 SetPropertyAtomic.init(&CGM,
"objc_setProperty_atomic", VoidTy, IdTy,
874 SelectorTy, IdTy, PtrDiffTy);
875 SetPropertyAtomicCopy.init(&CGM,
"objc_setProperty_atomic_copy", VoidTy,
876 IdTy, SelectorTy, IdTy, PtrDiffTy);
877 SetPropertyNonAtomic.init(&CGM,
"objc_setProperty_nonatomic", VoidTy,
878 IdTy, SelectorTy, IdTy, PtrDiffTy);
879 SetPropertyNonAtomicCopy.init(&CGM,
"objc_setProperty_nonatomic_copy",
880 VoidTy, IdTy, SelectorTy, IdTy, PtrDiffTy);
883 CxxAtomicObjectSetFn.init(&CGM,
"objc_setCppObjectAtomic", VoidTy, PtrTy,
887 CxxAtomicObjectGetFn.init(&CGM,
"objc_getCppObjectAtomic", VoidTy, PtrTy,
891 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override {
896 return CxxAtomicObjectGetFn;
899 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override {
904 return CxxAtomicObjectSetFn;
907 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
908 bool copy)
override {
912 assert ((CGM.
getLangOpts().getGC() == LangOptions::NonGC));
919 if (copy)
return SetPropertyAtomicCopy;
920 return SetPropertyAtomic;
923 return copy ? SetPropertyNonAtomicCopy : SetPropertyNonAtomic;
930class CGObjCGNUstep2 :
public CGObjCGNUstep {
935 ClassReferenceSection,
938 ProtocolReferenceSection,
940 ConstantStringSection
945 ClassFlagMeta = (1 << 0),
948 ClassFlagInitialized = (1 << 8),
950 static const char *
const SectionsBaseNames[8];
951 static const char *
const PECOFFSectionsBaseNames[8];
952 template<SectionKind K>
953 std::string sectionName() {
954 if (CGM.
getTriple().isOSBinFormatCOFF()) {
955 std::string
name(PECOFFSectionsBaseNames[K]);
959 return SectionsBaseNames[K];
964 LazyRuntimeFunction MsgLookupSuperFn;
966 LazyRuntimeFunction SentInitializeFn;
970 bool EmittedProtocol =
false;
975 bool EmittedProtocolRef =
false;
979 bool EmittedClass =
false;
983 typedef std::pair<std::string, std::pair<llvm::GlobalVariable*, int>>
985 std::vector<EarlyInitPair> EarlyInitList;
987 std::string SymbolForClassRef(StringRef Name,
bool isWeak) {
989 return (ManglePublicSymbol(
"OBJC_WEAK_REF_CLASS_") + Name).str();
991 return (ManglePublicSymbol(
"OBJC_REF_CLASS_") + Name).str();
994 std::string SymbolForClass(StringRef Name) {
995 return (ManglePublicSymbol(
"OBJC_CLASS_") + Name).str();
997 void CallRuntimeFunction(CGBuilderTy &B, StringRef FunctionName,
998 ArrayRef<llvm::Value*> Args) {
999 SmallVector<llvm::Type *,8> Types;
1000 for (
auto *Arg : Args)
1001 Types.push_back(Arg->getType());
1002 llvm::FunctionType *FT = llvm::FunctionType::get(B.getVoidTy(), Types,
1005 B.CreateCall(Fn, Args);
1008 ConstantAddress GenerateConstantString(
const StringLiteral *SL)
override {
1014 llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
1015 if (old != ObjCStrings.end())
1016 return ConstantAddress(old->getValue(), IdElemTy, Align);
1023 (LiteralLength < 9) && !isNonASCII) {
1029 for (
unsigned i=0 ; i<LiteralLength ; i++)
1030 str |= ((uint64_t)SL->
getCodeUnit(i)) << ((64 - 4 - 3) - (i*7));
1032 str |= LiteralLength << 3;
1035 auto *ObjCStr = llvm::ConstantExpr::getIntToPtr(
1036 llvm::ConstantInt::get(Int64Ty, str), IdTy);
1037 ObjCStrings[Str] = ObjCStr;
1038 return ConstantAddress(ObjCStr, IdElemTy, Align);
1043 if (StringClass.empty()) StringClass =
"NSConstantString";
1045 std::string Sym = SymbolForClass(StringClass);
1047 llvm::Constant *
isa = TheModule.getNamedGlobal(Sym);
1050 isa =
new llvm::GlobalVariable(TheModule, IdTy,
false,
1051 llvm::GlobalValue::ExternalLinkage,
nullptr, Sym);
1052 if (CGM.
getTriple().isOSBinFormatCOFF()) {
1067 ConstantInitBuilder Builder(CGM);
1068 auto Fields = Builder.beginStruct();
1069 if (!CGM.
getTriple().isOSBinFormatCOFF()) {
1079 unsigned NumU8CodeUnits = Str.size();
1083 SmallVector<llvm::UTF16, 128> ToBuf(NumU8CodeUnits + 1);
1084 const llvm::UTF8 *FromPtr = (
const llvm::UTF8 *)Str.data();
1085 llvm::UTF16 *ToPtr = &ToBuf[0];
1086 (void)llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumU8CodeUnits,
1087 &ToPtr, ToPtr + NumU8CodeUnits, llvm::strictConversion);
1088 uint32_t StringLength = ToPtr - &ToBuf[0];
1092 Fields.
addInt(Int32Ty, 2);
1094 Fields.
addInt(Int32Ty, StringLength);
1096 Fields.
addInt(Int32Ty, StringLength * 2);
1098 Fields.
addInt(Int32Ty, 0);
1100 auto Arr = llvm::ArrayRef(&ToBuf[0], ToPtr + 1);
1101 auto *
C = llvm::ConstantDataArray::get(VMContext, Arr);
1102 auto *Buffer =
new llvm::GlobalVariable(TheModule,
C->getType(),
1103 true, llvm::GlobalValue::PrivateLinkage,
C,
".str");
1104 Buffer->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1108 Fields.
addInt(Int32Ty, 0);
1110 Fields.
addInt(Int32Ty, Str.size());
1112 Fields.
addInt(Int32Ty, Str.size());
1114 Fields.
addInt(Int32Ty, 0);
1116 Fields.
add(MakeConstantString(Str));
1118 std::string StringName;
1121 StringName =
".objc_str_";
1122 for (
unsigned char c : Str) {
1133 llvm::GlobalVariable *ObjCStrGV =
1135 isNamed ? StringRef(StringName) :
".objc_string",
1136 Align,
false,
isNamed ? llvm::GlobalValue::LinkOnceODRLinkage
1137 : llvm::GlobalValue::PrivateLinkage);
1138 ObjCStrGV->setSection(sectionName<ConstantStringSection>());
1140 ObjCStrGV->setComdat(TheModule.getOrInsertComdat(StringName));
1141 ObjCStrGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1143 if (CGM.
getTriple().isOSBinFormatCOFF()) {
1144 std::pair<llvm::GlobalVariable*, int> v{ObjCStrGV, 0};
1145 EarlyInitList.emplace_back(Sym, v);
1147 ObjCStrings[Str] = ObjCStrGV;
1148 ConstantStrings.push_back(ObjCStrGV);
1149 return ConstantAddress(ObjCStrGV, IdElemTy, Align);
1152 void PushProperty(ConstantArrayBuilder &PropertiesArray,
1153 const ObjCPropertyDecl *property,
1155 bool isSynthesized=
true,
bool
1156 isDynamic=
true)
override {
1165 auto Fields = PropertiesArray.
beginStruct(PropertyMetadataTy);
1168 std::string TypeStr =
1170 Fields.
add(MakeConstantString(TypeStr));
1171 std::string typeStr;
1173 Fields.
add(MakeConstantString(typeStr));
1174 auto addPropertyMethod = [&](
const ObjCMethodDecl *accessor) {
1177 Fields.
add(GetConstantSelector(accessor->getSelector(), TypeStr));
1179 Fields.
add(NULLPtr);
1188 GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods)
override {
1194 llvm::StructType *ObjCMethodDescTy =
1196 { PtrToInt8Ty, PtrToInt8Ty });
1198 ConstantInitBuilder Builder(CGM);
1205 auto MethodList = Builder.beginStruct();
1207 MethodList.addInt(IntTy, Methods.size());
1209 const llvm::DataLayout &DL = TheModule.getDataLayout();
1210 MethodList.addInt(IntTy, DL.getTypeSizeInBits(ObjCMethodDescTy) /
1213 auto MethodArray = MethodList.beginArray(ObjCMethodDescTy);
1214 for (
auto *M : Methods) {
1215 auto Method = MethodArray.beginStruct(ObjCMethodDescTy);
1216 Method.add(CGObjCGNU::GetConstantSelector(M));
1218 Method.finishAndAddTo(MethodArray);
1220 MethodArray.finishAndAddTo(MethodList);
1221 return MethodList.finishAndCreateGlobal(
".objc_protocol_method_list",
1224 llvm::Constant *GenerateCategoryProtocolList(
const ObjCCategoryDecl *OCD)
1227 auto RuntimeProtocols = GetRuntimeProtocolList(ReferencedProtocols.begin(),
1228 ReferencedProtocols.end());
1229 SmallVector<llvm::Constant *, 16> Protocols;
1230 for (
const auto *PI : RuntimeProtocols)
1231 Protocols.push_back(GenerateProtocolRef(PI));
1232 return GenerateProtocolList(Protocols);
1235 llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
1236 llvm::Value *cmd, MessageSendInfo &MSI)
override {
1238 CGBuilderTy &Builder = CGF.
Builder;
1239 llvm::Value *lookupArgs[] = {
1246 llvm::GlobalVariable *GetClassVar(StringRef Name,
bool isWeak=
false) {
1247 std::string SymbolName = SymbolForClassRef(Name, isWeak);
1248 auto *ClassSymbol = TheModule.getNamedGlobal(SymbolName);
1251 ClassSymbol =
new llvm::GlobalVariable(TheModule,
1252 IdTy,
false, llvm::GlobalValue::ExternalLinkage,
1253 nullptr, SymbolName);
1259 ClassSymbol->setInitializer(
new llvm::GlobalVariable(TheModule,
1260 Int8Ty,
false, llvm::GlobalValue::ExternalWeakLinkage,
1261 nullptr, SymbolForClass(Name)));
1263 if (CGM.
getTriple().isOSBinFormatCOFF()) {
1268 const ObjCInterfaceDecl *OID =
nullptr;
1270 if ((OID = dyn_cast<ObjCInterfaceDecl>(
Result)))
1276 assert(OID &&
"Failed to find ObjCInterfaceDecl");
1278 if (OIDDef !=
nullptr)
1281 auto Storage = llvm::GlobalValue::DefaultStorageClass;
1282 if (OID->
hasAttr<DLLImportAttr>())
1283 Storage = llvm::GlobalValue::DLLImportStorageClass;
1284 else if (OID->
hasAttr<DLLExportAttr>())
1285 Storage = llvm::GlobalValue::DLLExportStorageClass;
1290 assert(ClassSymbol->getName() == SymbolName);
1293 llvm::Value *GetClassNamed(CodeGenFunction &CGF,
1294 const std::string &Name,
1295 bool isWeak)
override {
1307 switch (Ownership) {
1324 llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
1325 ArrayRef<llvm::Constant *> IvarTypes,
1326 ArrayRef<llvm::Constant *> IvarOffsets,
1327 ArrayRef<llvm::Constant *> IvarAlign,
1328 ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership)
override {
1329 llvm_unreachable(
"Method should not be called!");
1332 llvm::Constant *GenerateEmptyProtocol(StringRef ProtocolName)
override {
1333 std::string Name = SymbolForProtocol(ProtocolName);
1334 auto *GV = TheModule.getGlobalVariable(Name);
1337 GV =
new llvm::GlobalVariable(TheModule, ProtocolTy,
false,
1338 llvm::GlobalValue::ExternalLinkage,
nullptr, Name);
1345 llvm::StringMap<llvm::Constant*> ExistingProtocolRefs;
1347 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1348 const ObjCProtocolDecl *PD)
override {
1350 auto *&Ref = ExistingProtocolRefs[Name];
1352 auto *&
Protocol = ExistingProtocols[Name];
1354 Protocol = GenerateProtocolRef(PD);
1355 std::string RefName = SymbolForProtocolRef(Name);
1356 assert(!TheModule.getGlobalVariable(RefName));
1358 auto GV =
new llvm::GlobalVariable(TheModule, ProtocolPtrTy,
false,
1359 llvm::GlobalValue::LinkOnceODRLinkage,
1361 GV->setComdat(TheModule.getOrInsertComdat(RefName));
1362 GV->setSection(sectionName<ProtocolReferenceSection>());
1366 EmittedProtocolRef =
true;
1371 llvm::Constant *GenerateProtocolList(ArrayRef<llvm::Constant*> Protocols) {
1372 llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(ProtocolPtrTy,
1374 llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
1376 ConstantInitBuilder builder(CGM);
1377 auto ProtocolBuilder = builder.beginStruct();
1378 ProtocolBuilder.addNullPointer(PtrTy);
1379 ProtocolBuilder.addInt(SizeTy, Protocols.size());
1380 ProtocolBuilder.add(ProtocolArray);
1381 return ProtocolBuilder.finishAndCreateGlobal(
".objc_protocol_list",
1385 void GenerateProtocol(
const ObjCProtocolDecl *PD)
override {
1388 llvm::Constant *GenerateProtocolRef(
const ObjCProtocolDecl *PD)
override {
1390 auto *&
Protocol = ExistingProtocols[ProtocolName];
1394 EmittedProtocol =
true;
1396 auto SymName = SymbolForProtocol(ProtocolName);
1397 auto *OldGV = TheModule.getGlobalVariable(SymName);
1407 Protocol =
new llvm::GlobalVariable(TheModule, ProtocolTy,
1409 llvm::GlobalValue::ExternalLinkage,
nullptr, SymName);
1413 SmallVector<llvm::Constant*, 16> Protocols;
1414 auto RuntimeProtocols =
1416 for (
const auto *PI : RuntimeProtocols)
1417 Protocols.push_back(GenerateProtocolRef(PI));
1418 llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
1421 llvm::Constant *InstanceMethodList, *OptionalInstanceMethodList;
1422 llvm::Constant *ClassMethodList, *OptionalClassMethodList;
1424 OptionalInstanceMethodList);
1425 EmitProtocolMethodList(PD->
class_methods(), ClassMethodList,
1426 OptionalClassMethodList);
1430 ConstantInitBuilder builder(CGM);
1431 auto ProtocolBuilder = builder.beginStruct();
1432 ProtocolBuilder.add(llvm::ConstantExpr::getIntToPtr(
1433 llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
1434 ProtocolBuilder.add(MakeConstantString(ProtocolName));
1435 ProtocolBuilder.add(ProtocolList);
1436 ProtocolBuilder.add(InstanceMethodList);
1437 ProtocolBuilder.add(ClassMethodList);
1438 ProtocolBuilder.add(OptionalInstanceMethodList);
1439 ProtocolBuilder.add(OptionalClassMethodList);
1441 ProtocolBuilder.add(GeneratePropertyList(
nullptr, PD,
false,
false));
1443 ProtocolBuilder.add(GeneratePropertyList(
nullptr, PD,
false,
true));
1445 ProtocolBuilder.add(GeneratePropertyList(
nullptr, PD,
true,
false));
1447 ProtocolBuilder.add(GeneratePropertyList(
nullptr, PD,
true,
true));
1449 auto *GV = ProtocolBuilder.finishAndCreateGlobal(SymName,
1451 GV->setSection(sectionName<ProtocolSection>());
1452 GV->setComdat(TheModule.getOrInsertComdat(SymName));
1454 OldGV->replaceAllUsesWith(GV);
1455 OldGV->removeFromParent();
1456 GV->setName(SymName);
1461 llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
1462 const std::string &TypeEncoding)
override {
1463 return GetConstantSelector(Sel, TypeEncoding);
1465 std::string GetSymbolNameForTypeEncoding(
const std::string &TypeEncoding) {
1466 std::string MangledTypes = std::string(TypeEncoding);
1472 llvm::replace(MangledTypes,
'@',
'\1');
1475 llvm::replace(MangledTypes,
'=',
'\2');
1476 return MangledTypes;
1478 llvm::Constant *GetTypeString(llvm::StringRef TypeEncoding) {
1479 if (TypeEncoding.empty())
1481 std::string MangledTypes =
1482 GetSymbolNameForTypeEncoding(std::string(TypeEncoding));
1483 std::string TypesVarName =
".objc_sel_types_" + MangledTypes;
1484 auto *TypesGlobal = TheModule.getGlobalVariable(TypesVarName);
1486 llvm::Constant *
Init = llvm::ConstantDataArray::getString(VMContext,
1488 auto *GV =
new llvm::GlobalVariable(TheModule,
Init->getType(),
1489 true, llvm::GlobalValue::LinkOnceODRLinkage,
Init, TypesVarName);
1490 GV->setComdat(TheModule.getOrInsertComdat(TypesVarName));
1491 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1496 llvm::Constant *GetConstantSelector(Selector Sel,
1497 const std::string &TypeEncoding)
override {
1498 std::string MangledTypes = GetSymbolNameForTypeEncoding(TypeEncoding);
1499 auto SelVarName = (StringRef(
".objc_selector_") + Sel.
getAsString() +
"_" +
1500 MangledTypes).str();
1501 if (
auto *GV = TheModule.getNamedGlobal(SelVarName))
1503 ConstantInitBuilder builder(CGM);
1504 auto SelBuilder = builder.beginStruct();
1505 SelBuilder.add(ExportUniqueString(Sel.
getAsString(),
".objc_sel_name_",
1507 SelBuilder.add(GetTypeString(TypeEncoding));
1508 auto *GV = SelBuilder.finishAndCreateGlobal(SelVarName,
1510 GV->setComdat(TheModule.getOrInsertComdat(SelVarName));
1511 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1512 GV->setSection(sectionName<SelectorSection>());
1515 llvm::StructType *emptyStruct =
nullptr;
1524 std::pair<llvm::Constant*,llvm::Constant*>
1525 GetSectionBounds(StringRef Section) {
1526 if (CGM.
getTriple().isOSBinFormatCOFF()) {
1527 if (emptyStruct ==
nullptr) {
1528 emptyStruct = llvm::StructType::create(
1529 VMContext, {},
".objc_section_sentinel",
true);
1531 auto ZeroInit = llvm::Constant::getNullValue(emptyStruct);
1532 auto Sym = [&](StringRef Prefix, StringRef SecSuffix) {
1533 auto *Sym =
new llvm::GlobalVariable(TheModule, emptyStruct,
1535 llvm::GlobalValue::LinkOnceODRLinkage, ZeroInit, Prefix +
1537 Sym->setVisibility(llvm::GlobalValue::HiddenVisibility);
1538 Sym->setSection((Section + SecSuffix).str());
1539 Sym->setComdat(TheModule.getOrInsertComdat((Prefix +
1544 return { Sym(
"__start_",
"$a"), Sym(
"__stop",
"$z") };
1546 auto *Start =
new llvm::GlobalVariable(TheModule, PtrTy,
1548 llvm::GlobalValue::ExternalLinkage,
nullptr, StringRef(
"__start_") +
1550 Start->setVisibility(llvm::GlobalValue::HiddenVisibility);
1551 auto *Stop =
new llvm::GlobalVariable(TheModule, PtrTy,
1553 llvm::GlobalValue::ExternalLinkage,
nullptr, StringRef(
"__stop_") +
1555 Stop->setVisibility(llvm::GlobalValue::HiddenVisibility);
1556 return { Start, Stop };
1558 CatchTypeInfo getCatchAllTypeInfo()
override {
1561 llvm::Function *ModuleInitFunction()
override {
1562 llvm::Function *LoadFunction = llvm::Function::Create(
1563 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
false),
1564 llvm::GlobalValue::LinkOnceODRLinkage,
".objcv2_load_function",
1566 LoadFunction->setVisibility(llvm::GlobalValue::HiddenVisibility);
1567 LoadFunction->setComdat(TheModule.getOrInsertComdat(
".objcv2_load_function"));
1569 llvm::BasicBlock *EntryBB =
1570 llvm::BasicBlock::Create(VMContext,
"entry", LoadFunction);
1571 CGBuilderTy B(CGM, VMContext);
1572 B.SetInsertPoint(EntryBB);
1573 ConstantInitBuilder builder(CGM);
1574 auto InitStructBuilder = builder.beginStruct();
1575 InitStructBuilder.addInt(Int64Ty, 0);
1576 auto §ionVec = CGM.
getTriple().isOSBinFormatCOFF() ? PECOFFSectionsBaseNames : SectionsBaseNames;
1577 for (
auto *
s : sectionVec) {
1578 auto bounds = GetSectionBounds(
s);
1579 InitStructBuilder.add(bounds.first);
1580 InitStructBuilder.add(bounds.second);
1582 auto *InitStruct = InitStructBuilder.finishAndCreateGlobal(
".objc_init",
1584 InitStruct->setVisibility(llvm::GlobalValue::HiddenVisibility);
1585 InitStruct->setComdat(TheModule.getOrInsertComdat(
".objc_init"));
1587 CallRuntimeFunction(B,
"__objc_load", {InitStruct});;
1594 auto *InitVar =
new llvm::GlobalVariable(TheModule, LoadFunction->getType(),
1595 false, llvm::GlobalValue::LinkOnceAnyLinkage,
1596 LoadFunction,
".objc_ctor");
1599 assert(InitVar->getName() ==
".objc_ctor");
1605 if (CGM.
getTriple().isOSBinFormatCOFF())
1606 InitVar->setSection(
".CRT$XCLz");
1610 InitVar->setSection(
".init_array");
1612 InitVar->setSection(
".ctors");
1614 InitVar->setVisibility(llvm::GlobalValue::HiddenVisibility);
1615 InitVar->setComdat(TheModule.getOrInsertComdat(
".objc_ctor"));
1617 for (
auto *
C : Categories) {
1619 Cat->setSection(sectionName<CategorySection>());
1622 auto createNullGlobal = [&](StringRef Name, ArrayRef<llvm::Constant*>
Init,
1623 StringRef Section) {
1624 auto nullBuilder = builder.beginStruct();
1625 for (
auto *F :
Init)
1627 auto GV = nullBuilder.finishAndCreateGlobal(Name, CGM.
getPointerAlign(),
1628 false, llvm::GlobalValue::LinkOnceODRLinkage);
1629 GV->setSection(Section);
1630 GV->setComdat(TheModule.getOrInsertComdat(Name));
1631 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1635 for (
auto clsAlias : ClassAliases)
1636 createNullGlobal(std::string(
".objc_class_alias") +
1637 clsAlias.second, { MakeConstantString(clsAlias.second),
1638 GetClassVar(clsAlias.first) }, sectionName<ClassAliasSection>());
1643 if (!CGM.
getTriple().isOSBinFormatCOFF()) {
1644 createNullGlobal(
".objc_null_selector", {NULLPtr, NULLPtr},
1645 sectionName<SelectorSection>());
1646 if (Categories.empty())
1647 createNullGlobal(
".objc_null_category", {NULLPtr, NULLPtr,
1648 NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr},
1649 sectionName<CategorySection>());
1650 if (!EmittedClass) {
1651 createNullGlobal(
".objc_null_cls_init_ref", NULLPtr,
1652 sectionName<ClassSection>());
1653 createNullGlobal(
".objc_null_class_ref", { NULLPtr, NULLPtr },
1654 sectionName<ClassReferenceSection>());
1656 if (!EmittedProtocol)
1657 createNullGlobal(
".objc_null_protocol", {NULLPtr, NULLPtr, NULLPtr,
1658 NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr,
1659 NULLPtr}, sectionName<ProtocolSection>());
1660 if (!EmittedProtocolRef)
1661 createNullGlobal(
".objc_null_protocol_ref", {NULLPtr},
1662 sectionName<ProtocolReferenceSection>());
1663 if (ClassAliases.empty())
1664 createNullGlobal(
".objc_null_class_alias", { NULLPtr, NULLPtr },
1665 sectionName<ClassAliasSection>());
1666 if (ConstantStrings.empty()) {
1667 auto i32Zero = llvm::ConstantInt::get(Int32Ty, 0);
1668 createNullGlobal(
".objc_null_constant_string", { NULLPtr, i32Zero,
1669 i32Zero, i32Zero, i32Zero, NULLPtr },
1670 sectionName<ConstantStringSection>());
1673 ConstantStrings.clear();
1677 if (EarlyInitList.size() > 0) {
1678 auto *
Init = llvm::Function::Create(llvm::FunctionType::get(CGM.
VoidTy,
1679 {}), llvm::GlobalValue::InternalLinkage,
".objc_early_init",
1681 llvm::IRBuilder<>
b(llvm::BasicBlock::Create(CGM.
getLLVMContext(),
"entry",
1683 for (
const auto &lateInit : EarlyInitList) {
1684 auto *global = TheModule.getGlobalVariable(lateInit.first);
1686 llvm::GlobalVariable *GV = lateInit.second.first;
1687 b.CreateAlignedStore(
1689 b.CreateStructGEP(GV->getValueType(), GV, lateInit.second.second),
1696 auto *InitVar =
new llvm::GlobalVariable(CGM.
getModule(),
Init->getType(),
1697 true, llvm::GlobalValue::InternalLinkage,
1698 Init,
".objc_early_init_ptr");
1699 InitVar->setSection(
".CRT$XCLb");
1706 std::string GetIVarOffsetVariableName(
const ObjCInterfaceDecl *ID,
1707 const ObjCIvarDecl *Ivar)
override {
1708 std::string TypeEncoding;
1710 TypeEncoding = GetSymbolNameForTypeEncoding(TypeEncoding);
1711 const std::string Name =
"__objc_ivar_offset_" +
ID->getNameAsString()
1715 llvm::Value *EmitIvarOffset(CodeGenFunction &CGF,
1717 const ObjCIvarDecl *Ivar)
override {
1718 const ObjCInterfaceDecl *ContainingInterface =
1720 const std::string Name =
1721 GetIVarOffsetVariableName(ContainingInterface, Ivar);
1722 llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
1723 if (!IvarOffsetPointer) {
1724 IvarOffsetPointer =
new llvm::GlobalVariable(TheModule, IntTy,
false,
1725 llvm::GlobalValue::ExternalLinkage,
nullptr, Name);
1731 llvm::Value *Offset =
1733 if (Offset->getType() != PtrDiffTy)
1734 Offset = CGF.
Builder.CreateZExtOrBitCast(Offset, PtrDiffTy);
1737 void GenerateClass(
const ObjCImplementationDecl *OID)
override {
1739 bool IsCOFF = CGM.
getTriple().isOSBinFormatCOFF();
1742 ObjCInterfaceDecl *classDecl =
1745 auto *classNameConstant = MakeConstantString(className);
1747 ConstantInitBuilder builder(CGM);
1748 auto metaclassFields = builder.beginStruct();
1750 metaclassFields.addNullPointer(PtrTy);
1752 metaclassFields.addNullPointer(PtrTy);
1754 metaclassFields.add(classNameConstant);
1756 metaclassFields.addInt(LongTy, 0);
1759 metaclassFields.addInt(LongTy, ClassFlags::ClassFlagMeta);
1763 metaclassFields.addInt(LongTy, 0);
1765 metaclassFields.addNullPointer(PtrTy);
1770 metaclassFields.addNullPointer(PtrTy);
1772 SmallVector<ObjCMethodDecl*, 16> ClassMethods;
1775 metaclassFields.add(
1776 GenerateMethodList(className,
"", ClassMethods,
true));
1779 metaclassFields.addNullPointer(PtrTy);
1781 metaclassFields.addNullPointer(PtrTy);
1783 metaclassFields.addNullPointer(PtrTy);
1785 metaclassFields.addNullPointer(PtrTy);
1787 metaclassFields.addNullPointer(PtrTy);
1789 metaclassFields.addNullPointer(PtrTy);
1791 metaclassFields.addNullPointer(PtrTy);
1793 metaclassFields.addInt(LongTy, 0);
1795 metaclassFields.add(GeneratePropertyList(OID, classDecl,
true));
1797 auto *metaclass = metaclassFields.finishAndCreateGlobal(
1798 ManglePublicSymbol(
"OBJC_METACLASS_") + className,
1801 auto classFields = builder.beginStruct();
1803 classFields.add(metaclass);
1806 const ObjCInterfaceDecl * SuperClassDecl =
1808 llvm::Constant *SuperClass =
nullptr;
1809 if (SuperClassDecl) {
1810 auto SuperClassName = SymbolForClass(SuperClassDecl->
getNameAsString());
1811 SuperClass = TheModule.getNamedGlobal(SuperClassName);
1814 SuperClass =
new llvm::GlobalVariable(TheModule, PtrTy,
false,
1815 llvm::GlobalValue::ExternalLinkage,
nullptr, SuperClassName);
1817 auto Storage = llvm::GlobalValue::DefaultStorageClass;
1818 if (SuperClassDecl->
hasAttr<DLLImportAttr>())
1819 Storage = llvm::GlobalValue::DLLImportStorageClass;
1820 else if (SuperClassDecl->
hasAttr<DLLExportAttr>())
1821 Storage = llvm::GlobalValue::DLLExportStorageClass;
1827 classFields.add(SuperClass);
1829 classFields.addNullPointer(PtrTy);
1831 classFields.addNullPointer(PtrTy);
1833 classFields.
add(classNameConstant);
1835 classFields.addInt(LongTy, 0);
1838 classFields.addInt(LongTy, 0);
1840 int superInstanceSize = !SuperClassDecl ? 0 :
1853 classFields.addNullPointer(PtrTy);
1858 const llvm::DataLayout &DL = TheModule.getDataLayout();
1860 ConstantInitBuilder
b(CGM);
1861 auto ivarListBuilder =
b.beginStruct();
1863 ivarListBuilder.addInt(IntTy, ivar_count);
1865 llvm::StructType *ObjCIvarTy = llvm::StructType::get(
1871 ivarListBuilder.addInt(SizeTy, DL.getTypeSizeInBits(ObjCIvarTy) /
1874 auto ivarArrayBuilder = ivarListBuilder.beginArray();
1877 auto ivarTy = IVD->getType();
1878 auto ivarBuilder = ivarArrayBuilder.beginStruct();
1880 ivarBuilder.add(MakeConstantString(IVD->getNameAsString()));
1882 std::string TypeStr;
1885 ivarBuilder.add(MakeConstantString(TypeStr));
1887 uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
1888 uint64_t Offset = BaseOffset - superInstanceSize;
1889 llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset);
1890 std::string OffsetName = GetIVarOffsetVariableName(classDecl, IVD);
1891 llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName);
1893 OffsetVar->setInitializer(OffsetValue);
1895 OffsetVar =
new llvm::GlobalVariable(TheModule, IntTy,
1896 false, llvm::GlobalValue::ExternalLinkage,
1897 OffsetValue, OffsetName);
1898 auto ivarVisibility =
1902 llvm::GlobalValue::HiddenVisibility :
1903 llvm::GlobalValue::DefaultVisibility;
1904 OffsetVar->setVisibility(ivarVisibility);
1905 if (ivarVisibility != llvm::GlobalValue::HiddenVisibility)
1907 ivarBuilder.add(OffsetVar);
1909 ivarBuilder.addInt(Int32Ty,
1920 ivarBuilder.addInt(Int32Ty,
1921 (align << 3) | (1<<2) |
1922 FlagsForOwnership(ivarTy.getQualifiers().getObjCLifetime()));
1923 ivarBuilder.finishAndAddTo(ivarArrayBuilder);
1925 ivarArrayBuilder.finishAndAddTo(ivarListBuilder);
1926 auto ivarList = ivarListBuilder.finishAndCreateGlobal(
".objc_ivar_list",
1928 llvm::GlobalValue::PrivateLinkage);
1929 classFields.add(ivarList);
1932 SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
1933 InstanceMethods.insert(InstanceMethods.begin(), OID->
instmeth_begin(),
1936 if (propImpl->getPropertyImplementation() ==
1938 auto addIfExists = [&](
const ObjCMethodDecl *OMD) {
1939 if (OMD && OMD->hasBody())
1940 InstanceMethods.push_back(OMD);
1942 addIfExists(propImpl->getGetterMethodDecl());
1943 addIfExists(propImpl->getSetterMethodDecl());
1946 if (InstanceMethods.size() == 0)
1947 classFields.addNullPointer(PtrTy);
1950 GenerateMethodList(className,
"", InstanceMethods,
false));
1953 classFields.addNullPointer(PtrTy);
1955 classFields.addNullPointer(PtrTy);
1957 classFields.addNullPointer(PtrTy);
1959 classFields.addNullPointer(PtrTy);
1961 classFields.addNullPointer(PtrTy);
1963 auto RuntimeProtocols =
1966 SmallVector<llvm::Constant *, 16> Protocols;
1967 for (
const auto *I : RuntimeProtocols)
1968 Protocols.push_back(GenerateProtocolRef(I));
1970 if (Protocols.empty())
1971 classFields.addNullPointer(PtrTy);
1973 classFields.add(GenerateProtocolList(Protocols));
1975 classFields.addNullPointer(PtrTy);
1977 classFields.addInt(LongTy, 0);
1979 classFields.add(GeneratePropertyList(OID, classDecl));
1981 llvm::GlobalVariable *classStruct =
1982 classFields.finishAndCreateGlobal(SymbolForClass(className),
1985 auto *classRefSymbol = GetClassVar(className);
1986 classRefSymbol->setSection(sectionName<ClassReferenceSection>());
1987 classRefSymbol->setInitializer(classStruct);
1992 classStruct->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
1997 std::pair<llvm::GlobalVariable*, int> v{classStruct, 1};
1998 EarlyInitList.emplace_back(std::string(SuperClass->getName()),
2007 if (ClassPtrAlias) {
2008 ClassPtrAlias->replaceAllUsesWith(classStruct);
2009 ClassPtrAlias->eraseFromParent();
2010 ClassPtrAlias =
nullptr;
2012 if (
auto Placeholder =
2013 TheModule.getNamedGlobal(SymbolForClass(className)))
2014 if (Placeholder != classStruct) {
2015 Placeholder->replaceAllUsesWith(classStruct);
2016 Placeholder->eraseFromParent();
2017 classStruct->setName(SymbolForClass(className));
2019 if (MetaClassPtrAlias) {
2020 MetaClassPtrAlias->replaceAllUsesWith(metaclass);
2021 MetaClassPtrAlias->eraseFromParent();
2022 MetaClassPtrAlias =
nullptr;
2024 assert(classStruct->getName() == SymbolForClass(className));
2026 auto classInitRef =
new llvm::GlobalVariable(TheModule,
2027 classStruct->getType(),
false, llvm::GlobalValue::ExternalLinkage,
2028 classStruct, ManglePublicSymbol(
"OBJC_INIT_CLASS_") + className);
2029 classInitRef->setSection(sectionName<ClassSection>());
2032 EmittedClass =
true;
2035 CGObjCGNUstep2(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 10, 4, 2) {
2036 MsgLookupSuperFn.init(&CGM,
"objc_msg_lookup_super", IMPTy,
2037 PtrToObjCSuperTy, SelectorTy);
2038 SentInitializeFn.init(&CGM,
"objc_send_initialize",
2039 llvm::Type::getVoidTy(VMContext), IdTy);
2048 PropertyMetadataTy =
2050 { PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
2053 void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
2054 const ObjCMethodDecl *OMD,
2055 const ObjCContainerDecl *CD)
override {
2057 bool ReceiverCanBeNull =
true;
2059 auto selfValue = Builder.CreateLoad(selfAddr);
2084 ReceiverCanBeNull = isWeakLinkedClass(OID);
2088 if (ReceiverCanBeNull) {
2089 llvm::BasicBlock *SelfIsNilBlock =
2091 llvm::BasicBlock *ContBlock =
2096 auto Zero = llvm::ConstantPointerNull::get(selfTy);
2098 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue,
Zero),
2099 SelfIsNilBlock, ContBlock,
2100 MDHelper.createUnlikelyBranchWeights());
2106 Builder.SetInsertPoint(SelfIsNilBlock);
2107 if (!retTy->isVoidType()) {
2115 Builder.SetInsertPoint(ContBlock);
2121 llvm::StructType::get(PtrTy, PtrTy, PtrTy, LongTy, LongTy);
2128 llvm::Value *Val = Builder.CreateStructGEP(classStart, selfValue, 4);
2130 astContext.getTypeAlign(astContext.UnsignedLongTy));
2131 auto flags = Builder.CreateLoad(Address{Val, LongTy, Align});
2132 auto isInitialized =
2133 Builder.CreateAnd(flags, ClassFlags::ClassFlagInitialized);
2134 llvm::BasicBlock *notInitializedBlock =
2136 llvm::BasicBlock *initializedBlock =
2138 Builder.CreateCondBr(Builder.CreateICmpEQ(isInitialized, Zeros[0]),
2139 notInitializedBlock, initializedBlock,
2140 MDHelper.createUnlikelyBranchWeights());
2142 Builder.SetInsertPoint(notInitializedBlock);
2144 Builder.CreateBr(initializedBlock);
2146 Builder.SetInsertPoint(initializedBlock);
2154 Builder.CreateStore(GetSelector(CGF, OMD),
2160const char *
const CGObjCGNUstep2::SectionsBaseNames[8] =
2167"__objc_protocol_refs",
2168"__objc_class_aliases",
2169"__objc_constant_string"
2172const char *
const CGObjCGNUstep2::PECOFFSectionsBaseNames[8] =
2185class CGObjCObjFW:
public CGObjCGNU {
2189 LazyRuntimeFunction MsgLookupFn;
2192 LazyRuntimeFunction MsgLookupFnSRet;
2196 LazyRuntimeFunction MsgLookupSuperFn, MsgLookupSuperFnSRet;
2198 llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver,
2199 llvm::Value *cmd, llvm::MDNode *node,
2200 MessageSendInfo &MSI)
override {
2201 CGBuilderTy &Builder = CGF.
Builder;
2202 llvm::Value *args[] = {
2203 EnforceType(Builder, Receiver, IdTy),
2204 EnforceType(Builder, cmd, SelectorTy) };
2206 llvm::CallBase *imp;
2212 imp->setMetadata(msgSendMDKind, node);
2216 llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
2217 llvm::Value *cmd, MessageSendInfo &MSI)
override {
2218 CGBuilderTy &Builder = CGF.
Builder;
2219 llvm::Value *lookupArgs[] = {
2220 EnforceType(Builder, ObjCSuper.
emitRawPointer(CGF), PtrToObjCSuperTy),
2230 llvm::Value *GetClassNamed(CodeGenFunction &CGF,
const std::string &Name,
2231 bool isWeak)
override {
2233 return CGObjCGNU::GetClassNamed(CGF, Name, isWeak);
2236 std::string SymbolName =
"_OBJC_CLASS_" + Name;
2237 llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(SymbolName);
2239 ClassSymbol =
new llvm::GlobalVariable(TheModule, LongTy,
false,
2240 llvm::GlobalValue::ExternalLinkage,
2241 nullptr, SymbolName);
2245 void GenerateDirectMethodPrologue(
2246 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
2247 const ObjCContainerDecl *CD)
override {
2249 bool ReceiverCanBeNull =
true;
2251 auto selfValue = Builder.CreateLoad(selfAddr);
2270 "GenerateDirectMethod() should be called with the Class Interface");
2283 result = GeneratePossiblySpecializedMessageSend(
2284 CGF, ReturnValueSlot(), ResultType, SelfSel, selfValue, Args, OID,
2291 ReceiverCanBeNull = isWeakLinkedClass(OID);
2294 if (ReceiverCanBeNull) {
2295 llvm::BasicBlock *SelfIsNilBlock =
2297 llvm::BasicBlock *ContBlock =
2302 auto Zero = llvm::ConstantPointerNull::get(selfTy);
2305 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue,
Zero),
2306 SelfIsNilBlock, ContBlock,
2307 MDHelper.createUnlikelyBranchWeights());
2313 Builder.SetInsertPoint(SelfIsNilBlock);
2314 if (!retTy->isVoidType()) {
2322 Builder.SetInsertPoint(ContBlock);
2330 Builder.CreateStore(GetSelector(CGF, OMD),
2336 CGObjCObjFW(CodeGenModule &Mod): CGObjCGNU(Mod, 9, 3) {
2338 MsgLookupFn.init(&CGM,
"objc_msg_lookup", IMPTy, IdTy, SelectorTy);
2339 MsgLookupFnSRet.init(&CGM,
"objc_msg_lookup_stret", IMPTy, IdTy,
2342 MsgLookupSuperFn.init(&CGM,
"objc_msg_lookup_super", IMPTy,
2343 PtrToObjCSuperTy, SelectorTy);
2344 MsgLookupSuperFnSRet.init(&CGM,
"objc_msg_lookup_super_stret", IMPTy,
2345 PtrToObjCSuperTy, SelectorTy);
2353void CGObjCGNU::EmitClassRef(
const std::string &className) {
2354 std::string symbolRef =
"__objc_class_ref_" + className;
2356 if (TheModule.getGlobalVariable(symbolRef))
2358 std::string symbolName =
"__objc_class_name_" + className;
2359 llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName);
2361 ClassSymbol =
new llvm::GlobalVariable(TheModule, LongTy,
false,
2362 llvm::GlobalValue::ExternalLinkage,
2363 nullptr, symbolName);
2365 new llvm::GlobalVariable(TheModule, ClassSymbol->getType(),
true,
2366 llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef);
2369CGObjCGNU::CGObjCGNU(CodeGenModule &cgm,
unsigned runtimeABIVersion,
2370 unsigned protocolClassVersion,
unsigned classABI)
2371 : CGObjCRuntime(cgm), TheModule(CGM.getModule()),
2372 VMContext(cgm.getLLVMContext()), ClassPtrAlias(
nullptr),
2373 MetaClassPtrAlias(
nullptr), RuntimeVersion(runtimeABIVersion),
2374 ProtocolVersion(protocolClassVersion), ClassABIVersion(classABI) {
2376 msgSendMDKind = VMContext.getMDKindID(
"GNUObjCMessageSend");
2394 Int8Ty = llvm::Type::getInt8Ty(VMContext);
2399 PtrToInt8Ty = PtrTy;
2400 ProtocolPtrTy = PtrTy;
2402 Zeros[0] = llvm::ConstantInt::get(LongTy, 0);
2403 Zeros[1] = Zeros[0];
2404 NULLPtr = llvm::ConstantPointerNull::get(PtrToInt8Ty);
2408 SelectorTy = PtrToInt8Ty;
2409 SelectorElemTy = Int8Ty;
2415 Int32Ty = llvm::Type::getInt32Ty(VMContext);
2416 Int64Ty = llvm::Type::getInt64Ty(VMContext);
2419 CGM.
getDataLayout().getPointerSizeInBits() == 32 ? Int32Ty : Int64Ty;
2434 ProtocolTy = llvm::StructType::get(IdTy,
2456 PropertyMetadataTy = llvm::StructType::get(CGM.
getLLVMContext(), {
2457 PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty,
2458 PtrToInt8Ty, PtrToInt8Ty });
2460 ObjCSuperTy = llvm::StructType::get(IdTy, IdTy);
2461 PtrToObjCSuperTy = PtrTy;
2463 llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
2466 ExceptionThrowFn.init(&CGM,
"objc_exception_throw", VoidTy, IdTy);
2467 ExceptionReThrowFn.init(&CGM,
2468 usesCxxExceptions ?
"objc_exception_rethrow"
2469 :
"objc_exception_throw",
2472 SyncEnterFn.init(&CGM,
"objc_sync_enter", IntTy, IdTy);
2474 SyncExitFn.init(&CGM,
"objc_sync_exit", IntTy, IdTy);
2477 EnumerationMutationFn.init(&CGM,
"objc_enumerationMutation", VoidTy, IdTy);
2480 GetPropertyFn.init(&CGM,
"objc_getProperty", IdTy, IdTy, SelectorTy,
2483 SetPropertyFn.init(&CGM,
"objc_setProperty", VoidTy, IdTy, SelectorTy,
2484 PtrDiffTy, IdTy, BoolTy, BoolTy);
2486 GetStructPropertyFn.init(&CGM,
"objc_getPropertyStruct", VoidTy, PtrTy, PtrTy,
2487 PtrDiffTy, BoolTy, BoolTy);
2489 SetStructPropertyFn.init(&CGM,
"objc_setPropertyStruct", VoidTy, PtrTy, PtrTy,
2490 PtrDiffTy, BoolTy, BoolTy);
2497 RuntimeVersion = 10;
2512 IvarAssignFn.init(&CGM,
"objc_assign_ivar", IdTy, IdTy, IdTy, PtrDiffTy);
2514 StrongCastAssignFn.init(&CGM,
"objc_assign_strongCast", IdTy, IdTy,
2517 GlobalAssignFn.init(&CGM,
"objc_assign_global", IdTy, IdTy, PtrToIdTy);
2519 WeakAssignFn.init(&CGM,
"objc_assign_weak", IdTy, IdTy, PtrToIdTy);
2521 WeakReadFn.init(&CGM,
"objc_read_weak", IdTy, PtrToIdTy);
2523 MemMoveFn.init(&CGM,
"objc_memmove_collectable", PtrTy, PtrTy, PtrTy,
2529 const std::string &Name,
bool isWeak) {
2530 llvm::Constant *ClassName = MakeConstantString(Name);
2542 llvm::FunctionType::get(IdTy, PtrToInt8Ty,
true),
"objc_lookup_class");
2548llvm::Value *CGObjCGNU::GetClass(CodeGenFunction &CGF,
2549 const ObjCInterfaceDecl *OID) {
2552 if (
auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(
Value))
2557llvm::Value *CGObjCGNU::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
2558 auto *
Value = GetClassNamed(CGF,
"NSAutoreleasePool",
false);
2559 if (CGM.
getTriple().isOSBinFormatCOFF()) {
2560 if (
auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(
Value)) {
2565 const VarDecl *VD =
nullptr;
2567 if ((VD = dyn_cast<VarDecl>(
Result)))
2576llvm::Value *CGObjCGNU::GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
2577 const std::string &TypeEncoding) {
2578 SmallVectorImpl<TypedSelector> &Types = SelectorTable[Sel];
2579 llvm::GlobalAlias *SelValue =
nullptr;
2581 for (
const TypedSelector &
Type : Types) {
2582 if (
Type.first == TypeEncoding) {
2583 SelValue =
Type.second;
2588 SelValue = llvm::GlobalAlias::create(SelectorElemTy, 0,
2589 llvm::GlobalValue::PrivateLinkage,
2592 Types.emplace_back(TypeEncoding, SelValue);
2598Address CGObjCGNU::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
2599 llvm::Value *SelValue = GetSelector(CGF, Sel);
2609llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel) {
2610 return GetTypedSelector(CGF, Sel, std::string());
2613llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF,
2614 const ObjCMethodDecl *
Method) {
2616 return GetTypedSelector(CGF,
Method->getSelector(), SelTypes);
2619llvm::Constant *CGObjCGNU::GetEHType(QualType T) {
2626 return MakeConstantString(
"@id");
2633 const ObjCObjectPointerType *OPT = T->
getAs<ObjCObjectPointerType>();
2634 assert(OPT &&
"Invalid @catch type.");
2635 const ObjCInterfaceDecl *IDecl = OPT->
getObjectType()->getInterface();
2636 assert(IDecl &&
"Invalid @catch type.");
2640llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) {
2641 if (usesSEHExceptions)
2644 if (!CGM.
getLangOpts().CPlusPlus && !usesCxxExceptions)
2645 return CGObjCGNU::GetEHType(T);
2653 llvm::Constant *IDEHType =
2654 CGM.
getModule().getGlobalVariable(
"__objc_id_type_info");
2657 new llvm::GlobalVariable(CGM.
getModule(), PtrToInt8Ty,
2659 llvm::GlobalValue::ExternalLinkage,
2660 nullptr,
"__objc_id_type_info");
2664 const ObjCObjectPointerType *PT =
2665 T->
getAs<ObjCObjectPointerType>();
2666 assert(PT &&
"Invalid @catch type.");
2668 assert(IT &&
"Invalid @catch type.");
2669 std::string className =
2672 std::string typeinfoName =
"__objc_eh_typeinfo_" + className;
2675 if (llvm::Constant *typeinfo = TheModule.getGlobalVariable(typeinfoName))
2683 const char *vtableName =
"_ZTVN7gnustep7libobjc22__objc_class_type_infoE";
2684 auto *Vtable = TheModule.getGlobalVariable(vtableName);
2686 Vtable =
new llvm::GlobalVariable(TheModule, PtrToInt8Ty,
true,
2687 llvm::GlobalValue::ExternalLinkage,
2688 nullptr, vtableName);
2690 llvm::Constant *Two = llvm::ConstantInt::get(IntTy, 2);
2692 llvm::ConstantExpr::getGetElementPtr(Vtable->getValueType(), Vtable, Two);
2694 llvm::Constant *typeName =
2695 ExportUniqueString(className,
"__objc_eh_typename_");
2697 ConstantInitBuilder builder(CGM);
2698 auto fields = builder.beginStruct();
2699 fields.add(BVtable);
2700 fields.add(typeName);
2701 llvm::Constant *TI =
2702 fields.finishAndCreateGlobal(
"__objc_eh_typeinfo_" + className,
2705 llvm::GlobalValue::LinkOnceODRLinkage);
2710ConstantAddress CGObjCGNU::GenerateConstantString(
const StringLiteral *SL) {
2712 std::string Str = SL->
getString().str();
2716 llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
2717 if (old != ObjCStrings.end())
2718 return ConstantAddress(old->getValue(), Int8Ty, Align);
2722 if (StringClass.empty()) StringClass =
"NSConstantString";
2724 std::string Sym =
"_OBJC_CLASS_";
2727 llvm::Constant *
isa = TheModule.getNamedGlobal(Sym);
2730 isa =
new llvm::GlobalVariable(TheModule, IdTy,
false,
2731 llvm::GlobalValue::ExternalWeakLinkage,
2734 ConstantInitBuilder Builder(CGM);
2735 auto Fields = Builder.beginStruct();
2737 Fields.
add(MakeConstantString(Str));
2738 Fields.
addInt(IntTy, Str.size());
2740 ObjCStrings[Str] = ObjCStr;
2741 ConstantStrings.push_back(ObjCStr);
2742 return ConstantAddress(ObjCStr, Int8Ty, Align);
2745ConstantAddress CGObjCGNU::GenerateConstantNumber(
const bool Value,
2746 const QualType &Ty) {
2747 llvm_unreachable(
"Method should not be called, no GNU runtimes provide these "
2748 "or support ObjC number literal constant initializers");
2751ConstantAddress CGObjCGNU::GenerateConstantNumber(
const llvm::APSInt &
Value,
2752 const QualType &Ty) {
2753 llvm_unreachable(
"Method should not be called, no GNU runtimes provide these "
2754 "or support ObjC number literal constant initializers");
2757ConstantAddress CGObjCGNU::GenerateConstantNumber(
const llvm::APFloat &
Value,
2758 const QualType &Ty) {
2759 llvm_unreachable(
"Method should not be called, no GNU runtimes provide these "
2760 "or support ObjC number literal constant initializers");
2764CGObjCGNU::GenerateConstantArray(
const ArrayRef<llvm::Constant *> &Objects) {
2765 llvm_unreachable(
"Method should not be called, no GNU runtimes provide these "
2766 "or support ObjC array literal constant initializers");
2769ConstantAddress CGObjCGNU::GenerateConstantDictionary(
2770 const ObjCDictionaryLiteral *E,
2771 ArrayRef<std::pair<llvm::Constant *, llvm::Constant *>> KeysAndObjects) {
2772 llvm_unreachable(
"Method should not be called, no GNU runtimes provide these "
2773 "or support ObjC dictionary literal constant initializers");
2780CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF,
2781 ReturnValueSlot Return,
2782 QualType ResultType,
2784 const ObjCInterfaceDecl *
Class,
2785 bool isCategoryImpl,
2786 llvm::Value *Receiver,
2787 bool IsClassMessage,
2788 const CallArgList &CallArgs,
2789 const ObjCMethodDecl *
Method) {
2790 CGBuilderTy &Builder = CGF.
Builder;
2791 if (CGM.
getLangOpts().getGC() == LangOptions::GCOnly) {
2792 if (Sel == RetainSel || Sel == AutoreleaseSel) {
2796 if (Sel == ReleaseSel) {
2801 llvm::Value *cmd = GetSelector(CGF, Sel);
2802 CallArgList ActualArgs;
2804 ActualArgs.
add(
RValue::get(EnforceType(Builder, Receiver, IdTy)), ASTIdTy);
2808 MessageSendInfo MSI = getMessageSendInfo(
Method, ResultType, ActualArgs);
2810 llvm::Value *ReceiverClass =
nullptr;
2813 ReceiverClass = GetClassNamed(CGF,
2814 Class->getSuperClass()->getNameAsString(),
false);
2815 if (IsClassMessage) {
2818 Builder.CreateAlignedLoad(IdTy, ReceiverClass, CGF.
getPointerAlign());
2820 ReceiverClass = EnforceType(Builder, ReceiverClass, IdTy);
2822 if (isCategoryImpl) {
2823 llvm::FunctionCallee classLookupFunction =
nullptr;
2824 if (IsClassMessage) {
2826 IdTy, PtrTy,
true),
"objc_get_meta_class");
2829 IdTy, PtrTy,
true),
"objc_get_class");
2831 ReceiverClass = Builder.CreateCall(classLookupFunction,
2832 MakeConstantString(
Class->getNameAsString()));
2839 if (IsClassMessage) {
2840 if (!MetaClassPtrAlias) {
2841 MetaClassPtrAlias = llvm::GlobalAlias::create(
2842 IdElemTy, 0, llvm::GlobalValue::InternalLinkage,
2843 ".objc_metaclass_ref" +
Class->getNameAsString(), &TheModule);
2845 ReceiverClass = MetaClassPtrAlias;
2847 if (!ClassPtrAlias) {
2848 ClassPtrAlias = llvm::GlobalAlias::create(
2849 IdElemTy, 0, llvm::GlobalValue::InternalLinkage,
2850 ".objc_class_ref" +
Class->getNameAsString(), &TheModule);
2852 ReceiverClass = ClassPtrAlias;
2856 llvm::Type *CastTy = llvm::StructType::get(IdTy, IdTy);
2858 ReceiverClass = Builder.CreateStructGEP(CastTy, ReceiverClass, 1);
2861 Builder.CreateAlignedLoad(IdTy, ReceiverClass, CGF.
getPointerAlign());
2864 llvm::StructType *ObjCSuperTy =
2865 llvm::StructType::get(Receiver->getType(), IdTy);
2870 Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0));
2871 Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1));
2874 llvm::Value *imp = LookupIMPSuper(CGF, ObjCSuper, cmd, MSI);
2875 imp = EnforceType(Builder, imp, MSI.MessengerType);
2877 llvm::Metadata *impMD[] = {
2878 llvm::MDString::get(VMContext, Sel.
getAsString()),
2879 llvm::MDString::get(VMContext,
Class->getSuperClass()->getNameAsString()),
2880 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2881 llvm::Type::getInt1Ty(VMContext), IsClassMessage))};
2882 llvm::MDNode *
node = llvm::MDNode::get(VMContext, impMD);
2884 CGCallee callee(CGCalleeInfo(), imp);
2886 llvm::CallBase *call;
2887 RValue msgRet = CGF.
EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
2888 call->setMetadata(msgSendMDKind, node);
2894CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
2895 ReturnValueSlot Return,
2896 QualType ResultType,
2898 llvm::Value *Receiver,
2899 const CallArgList &CallArgs,
2900 const ObjCInterfaceDecl *
Class,
2901 const ObjCMethodDecl *
Method) {
2902 CGBuilderTy &Builder = CGF.
Builder;
2905 if (CGM.
getLangOpts().getGC() == LangOptions::GCOnly) {
2906 if (Sel == RetainSel || Sel == AutoreleaseSel) {
2910 if (Sel == ReleaseSel) {
2921 cmd = GetSelector(CGF,
Method);
2923 cmd = GetSelector(CGF, Sel);
2924 cmd = EnforceType(Builder, cmd, SelectorTy);
2927 Receiver = EnforceType(Builder, Receiver, IdTy);
2929 llvm::Metadata *impMD[] = {
2930 llvm::MDString::get(VMContext, Sel.
getAsString()),
2931 llvm::MDString::get(VMContext,
Class ?
Class->getNameAsString() :
""),
2932 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2933 llvm::Type::getInt1Ty(VMContext),
Class !=
nullptr))};
2934 llvm::MDNode *
node = llvm::MDNode::get(VMContext, impMD);
2936 CallArgList ActualArgs;
2942 MessageSendInfo MSI = getMessageSendInfo(
Method, ResultType, ActualArgs);
2963 bool hasParamDestroyedInCallee =
false;
2964 bool requiresExplicitZeroResult =
false;
2965 bool requiresNilReceiverCheck = [&] {
2967 if (!canMessageReceiverBeNull(CGF,
Method,
false,
2973 hasParamDestroyedInCallee =
true;
2994 requiresExplicitZeroResult = !isDirect;
2998 return hasParamDestroyedInCallee || requiresExplicitZeroResult;
3004 bool requiresExplicitAggZeroing =
3008 llvm::BasicBlock *continueBB =
nullptr;
3010 llvm::BasicBlock *nilPathBB =
nullptr;
3012 llvm::BasicBlock *nilCleanupBB =
nullptr;
3015 if (requiresNilReceiverCheck) {
3022 if (requiresExplicitAggZeroing || hasParamDestroyedInCallee) {
3025 nilPathBB = Builder.GetInsertBlock();
3028 llvm::Value *isNil = Builder.CreateICmpEQ(Receiver,
3029 llvm::Constant::getNullValue(Receiver->getType()));
3030 Builder.CreateCondBr(isNil, nilCleanupBB ? nilCleanupBB : continueBB,
3040 imp = GenerateMethod(
Method,
Method->getClassInterface());
3047 imp = LookupIMP(CGF, Receiver, cmd, node, MSI);
3051 StringRef
name =
"objc_msgSend";
3053 name =
"objc_msgSend_fpret";
3055 name =
"objc_msgSend_stret";
3059 bool shouldCheckForInReg =
3063 .isWindowsMSVCEnvironment() &&
3066 name =
"objc_msgSend_stret2";
3077 ActualArgs[0] = CallArg(
RValue::get(Receiver), ASTIdTy);
3079 imp = EnforceType(Builder, imp, MSI.MessengerType);
3081 llvm::CallBase *call;
3082 CGCallee callee(CGCalleeInfo(), imp);
3083 RValue msgRet = CGF.
EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
3085 call->setMetadata(msgSendMDKind, node);
3087 if (requiresNilReceiverCheck) {
3088 llvm::BasicBlock *nonNilPathBB = CGF.
Builder.GetInsertBlock();
3089 CGF.
Builder.CreateBr(continueBB);
3095 if (hasParamDestroyedInCallee) {
3096 destroyCalleeDestroyedArguments(CGF,
Method, CallArgs);
3099 if (requiresExplicitAggZeroing) {
3105 nilPathBB = CGF.
Builder.GetInsertBlock();
3106 CGF.
Builder.CreateBr(continueBB);
3114 llvm::PHINode *phi = Builder.CreatePHI(v->getType(), 2);
3115 phi->addIncoming(v, nonNilPathBB);
3122 std::pair<llvm::Value*,llvm::Value*> v = msgRet.
getComplexVal();
3123 llvm::PHINode *phi = Builder.CreatePHI(v.first->getType(), 2);
3124 phi->addIncoming(v.first, nonNilPathBB);
3125 phi->addIncoming(llvm::Constant::getNullValue(v.first->getType()),
3127 llvm::PHINode *phi2 = Builder.CreatePHI(v.second->getType(), 2);
3128 phi2->addIncoming(v.second, nonNilPathBB);
3129 phi2->addIncoming(llvm::Constant::getNullValue(v.second->getType()),
3139llvm::Constant *CGObjCGNU::
3140GenerateMethodList(StringRef ClassName,
3141 StringRef CategoryName,
3142 ArrayRef<const ObjCMethodDecl*> Methods,
3143 bool isClassMethodList) {
3144 if (Methods.empty())
3147 ConstantInitBuilder Builder(CGM);
3149 auto MethodList = Builder.beginStruct();
3150 MethodList.addNullPointer(CGM.
Int8PtrTy);
3151 MethodList.addInt(Int32Ty, Methods.size());
3154 llvm::StructType *ObjCMethodTy =
3163 const llvm::DataLayout &DL = TheModule.getDataLayout();
3164 MethodList.addInt(SizeTy, DL.getTypeSizeInBits(ObjCMethodTy) /
3180 auto MethodArray = MethodList.beginArray();
3182 for (
const auto *OMD : Methods) {
3183 llvm::Constant *FnPtr =
3184 TheModule.getFunction(getSymbolNameForMethod(OMD));
3185 assert(FnPtr &&
"Can't generate metadata for method that doesn't exist");
3186 auto Method = MethodArray.beginStruct(ObjCMethodTy);
3197 Method.finishAndAddTo(MethodArray);
3199 MethodArray.finishAndAddTo(MethodList);
3202 return MethodList.finishAndCreateGlobal(
".objc_method_list",
3207llvm::Constant *CGObjCGNU::
3208GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
3209 ArrayRef<llvm::Constant *> IvarTypes,
3210 ArrayRef<llvm::Constant *> IvarOffsets,
3211 ArrayRef<llvm::Constant *> IvarAlign,
3212 ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership) {
3213 if (IvarNames.empty())
3216 ConstantInitBuilder Builder(CGM);
3219 auto IvarList = Builder.beginStruct();
3220 IvarList.addInt(IntTy, (
int)IvarNames.size());
3223 llvm::StructType *ObjCIvarTy =
3224 llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy);
3227 auto Ivars = IvarList.beginArray(ObjCIvarTy);
3228 for (
unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
3229 auto Ivar = Ivars.beginStruct(ObjCIvarTy);
3230 Ivar.
add(IvarNames[i]);
3231 Ivar.
add(IvarTypes[i]);
3232 Ivar.
add(IvarOffsets[i]);
3233 Ivar.finishAndAddTo(Ivars);
3235 Ivars.finishAndAddTo(IvarList);
3238 return IvarList.finishAndCreateGlobal(
".objc_ivar_list",
3243llvm::Constant *CGObjCGNU::GenerateClassStructure(
3244 llvm::Constant *MetaClass,
3245 llvm::Constant *SuperClass,
3248 llvm::Constant *Version,
3249 llvm::Constant *InstanceSize,
3250 llvm::Constant *IVars,
3251 llvm::Constant *Methods,
3252 llvm::Constant *Protocols,
3253 llvm::Constant *IvarOffsets,
3254 llvm::Constant *Properties,
3255 llvm::Constant *StrongIvarBitmap,
3256 llvm::Constant *WeakIvarBitmap,
3265 llvm::StructType *ClassTy = llvm::StructType::get(
3282 IvarOffsets->getType(),
3283 Properties->getType(),
3288 ConstantInitBuilder Builder(CGM);
3289 auto Elements = Builder.beginStruct(ClassTy);
3294 Elements.add(MetaClass);
3296 Elements.add(SuperClass);
3298 Elements.add(MakeConstantString(Name,
".class_name"));
3300 Elements.addInt(LongTy, 0);
3302 Elements.addInt(LongTy, info);
3305 const llvm::DataLayout &DL = TheModule.getDataLayout();
3306 Elements.addInt(LongTy, DL.getTypeSizeInBits(ClassTy) /
3309 Elements.add(InstanceSize);
3311 Elements.add(IVars);
3313 Elements.add(Methods);
3316 Elements.add(NULLPtr);
3318 Elements.add(NULLPtr);
3320 Elements.add(NULLPtr);
3322 Elements.add(Protocols);
3324 Elements.add(NULLPtr);
3326 Elements.addInt(LongTy, ClassABIVersion);
3328 Elements.add(IvarOffsets);
3330 Elements.add(Properties);
3332 Elements.add(StrongIvarBitmap);
3334 Elements.add(WeakIvarBitmap);
3339 std::string ClassSym((isMeta ?
"_OBJC_METACLASS_":
"_OBJC_CLASS_") +
3341 llvm::GlobalVariable *ClassRef = TheModule.getNamedGlobal(ClassSym);
3342 llvm::Constant *
Class =
3343 Elements.finishAndCreateGlobal(ClassSym, CGM.
getPointerAlign(),
false,
3344 llvm::GlobalValue::ExternalLinkage);
3346 ClassRef->replaceAllUsesWith(
Class);
3347 ClassRef->removeFromParent();
3348 Class->setName(ClassSym);
3353llvm::Constant *CGObjCGNU::
3354GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods) {
3356 llvm::StructType *ObjCMethodDescTy =
3357 llvm::StructType::get(CGM.
getLLVMContext(), { PtrToInt8Ty, PtrToInt8Ty });
3359 ConstantInitBuilder Builder(CGM);
3360 auto MethodList = Builder.beginStruct();
3361 MethodList.addInt(IntTy, Methods.size());
3362 auto MethodArray = MethodList.beginArray(ObjCMethodDescTy);
3363 for (
auto *M : Methods) {
3364 auto Method = MethodArray.beginStruct(ObjCMethodDescTy);
3365 Method.add(MakeConstantString(M->getSelector().getAsString()));
3367 Method.finishAndAddTo(MethodArray);
3369 MethodArray.finishAndAddTo(MethodList);
3370 return MethodList.finishAndCreateGlobal(
".objc_method_list",
3376CGObjCGNU::GenerateProtocolList(ArrayRef<std::string> Protocols) {
3378 ConstantInitBuilder Builder(CGM);
3379 auto ProtocolList = Builder.beginStruct();
3380 ProtocolList.add(NULLPtr);
3381 ProtocolList.addInt(LongTy, Protocols.size());
3383 auto Elements = ProtocolList.beginArray(PtrToInt8Ty);
3384 for (
const std::string &Protocol : Protocols) {
3385 llvm::Constant *protocol =
nullptr;
3386 llvm::StringMap<llvm::Constant *>::iterator value =
3387 ExistingProtocols.find(Protocol);
3388 if (value == ExistingProtocols.end()) {
3389 protocol = GenerateEmptyProtocol(Protocol);
3391 protocol = value->getValue();
3393 Elements.add(protocol);
3395 Elements.finishAndAddTo(ProtocolList);
3396 return ProtocolList.finishAndCreateGlobal(
".objc_protocol_list",
3400llvm::Value *CGObjCGNU::GenerateProtocolRef(CodeGenFunction &CGF,
3401 const ObjCProtocolDecl *PD) {
3402 return GenerateProtocolRef(PD);
3405llvm::Constant *CGObjCGNU::GenerateProtocolRef(
const ObjCProtocolDecl *PD) {
3408 GenerateProtocol(PD);
3409 assert(protocol &&
"Unknown protocol");
3414CGObjCGNU::GenerateEmptyProtocol(StringRef ProtocolName) {
3415 llvm::Constant *ProtocolList = GenerateProtocolList({});
3416 llvm::Constant *MethodList = GenerateProtocolMethodList({});
3419 ConstantInitBuilder Builder(CGM);
3420 auto Elements = Builder.beginStruct();
3424 Elements.add(llvm::ConstantExpr::getIntToPtr(
3425 llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
3427 Elements.add(MakeConstantString(ProtocolName,
".objc_protocol_name"));
3428 Elements.add(ProtocolList);
3429 Elements.add(MethodList);
3430 Elements.add(MethodList);
3431 Elements.add(MethodList);
3432 Elements.add(MethodList);
3433 Elements.add(NULLPtr);
3434 Elements.add(NULLPtr);
3435 return Elements.finishAndCreateGlobal(SymbolForProtocol(ProtocolName),
3439void CGObjCGNU::GenerateProtocol(
const ObjCProtocolDecl *PD) {
3449 SmallVector<std::string, 16> Protocols;
3451 Protocols.push_back(PI->getNameAsString());
3452 SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
3453 SmallVector<const ObjCMethodDecl*, 16> OptionalInstanceMethods;
3455 if (I->isOptional())
3456 OptionalInstanceMethods.push_back(I);
3458 InstanceMethods.push_back(I);
3460 SmallVector<const ObjCMethodDecl*, 16> ClassMethods;
3461 SmallVector<const ObjCMethodDecl*, 16> OptionalClassMethods;
3463 if (I->isOptional())
3464 OptionalClassMethods.push_back(I);
3466 ClassMethods.push_back(I);
3468 llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
3469 llvm::Constant *InstanceMethodList =
3470 GenerateProtocolMethodList(InstanceMethods);
3471 llvm::Constant *ClassMethodList =
3472 GenerateProtocolMethodList(ClassMethods);
3473 llvm::Constant *OptionalInstanceMethodList =
3474 GenerateProtocolMethodList(OptionalInstanceMethods);
3475 llvm::Constant *OptionalClassMethodList =
3476 GenerateProtocolMethodList(OptionalClassMethods);
3484 llvm::Constant *PropertyList =
3485 GeneratePropertyList(
nullptr, PD,
false,
false);
3486 llvm::Constant *OptionalPropertyList =
3487 GeneratePropertyList(
nullptr, PD,
false,
true);
3493 ConstantInitBuilder Builder(CGM);
3494 auto Elements = Builder.beginStruct();
3496 llvm::ConstantExpr::getIntToPtr(
3497 llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
3498 Elements.add(MakeConstantString(ProtocolName));
3499 Elements.add(ProtocolList);
3500 Elements.add(InstanceMethodList);
3501 Elements.add(ClassMethodList);
3502 Elements.add(OptionalInstanceMethodList);
3503 Elements.add(OptionalClassMethodList);
3504 Elements.add(PropertyList);
3505 Elements.add(OptionalPropertyList);
3506 ExistingProtocols[ProtocolName] =
3507 Elements.finishAndCreateGlobal(
".objc_protocol", CGM.
getPointerAlign());
3509void CGObjCGNU::GenerateProtocolHolderCategory() {
3512 ConstantInitBuilder Builder(CGM);
3513 auto Elements = Builder.beginStruct();
3515 const std::string ClassName =
"__ObjC_Protocol_Holder_Ugly_Hack";
3516 const std::string CategoryName =
"AnotherHack";
3517 Elements.add(MakeConstantString(CategoryName));
3518 Elements.add(MakeConstantString(ClassName));
3520 Elements.add(GenerateMethodList(ClassName, CategoryName, {},
false));
3522 Elements.add(GenerateMethodList(ClassName, CategoryName, {},
true));
3525 ConstantInitBuilder ProtocolListBuilder(CGM);
3526 auto ProtocolList = ProtocolListBuilder.beginStruct();
3527 ProtocolList.add(NULLPtr);
3528 ProtocolList.addInt(LongTy, ExistingProtocols.size());
3529 auto ProtocolElements = ProtocolList.beginArray(PtrTy);
3530 for (
auto iter = ExistingProtocols.begin(), endIter = ExistingProtocols.end();
3531 iter != endIter ; iter++) {
3532 ProtocolElements.add(iter->getValue());
3534 ProtocolElements.finishAndAddTo(ProtocolList);
3535 Elements.add(ProtocolList.finishAndCreateGlobal(
".objc_protocol_list",
3537 Categories.push_back(
3552llvm::Constant *CGObjCGNU::MakeBitField(ArrayRef<bool> bits) {
3553 int bitCount = bits.size();
3555 if (bitCount < ptrBits) {
3557 for (
int i=0 ; i<bitCount ; ++i) {
3558 if (bits[i]) val |= 1ULL<<(i+1);
3560 return llvm::ConstantInt::get(IntPtrTy, val);
3562 SmallVector<llvm::Constant *, 8> values;
3564 while (v < bitCount) {
3566 for (
int i=0 ; (i<32) && (v<bitCount) ; ++i) {
3567 if (bits[v]) word |= 1<<i;
3570 values.push_back(llvm::ConstantInt::get(Int32Ty, word));
3573 ConstantInitBuilder builder(CGM);
3574 auto fields = builder.beginStruct();
3575 fields.addInt(Int32Ty, values.size());
3576 auto array = fields.beginArray();
3577 for (
auto *v : values) array.add(v);
3578 array.finishAndAddTo(fields);
3580 llvm::Constant *GS =
3582 llvm::Constant *ptr = llvm::ConstantExpr::getPtrToInt(GS, IntPtrTy);
3586llvm::Constant *CGObjCGNU::GenerateCategoryProtocolList(
const
3587 ObjCCategoryDecl *OCD) {
3589 const auto RuntimeProtos =
3590 GetRuntimeProtocolList(RefPro.begin(), RefPro.end());
3591 SmallVector<std::string, 16> Protocols;
3592 for (
const auto *PD : RuntimeProtos)
3594 return GenerateProtocolList(Protocols);
3597void CGObjCGNU::GenerateCategory(
const ObjCCategoryImplDecl *OCD) {
3599 std::string ClassName =
Class->getNameAsString();
3605 ConstantInitBuilder Builder(CGM);
3606 auto Elements = Builder.beginStruct();
3607 Elements.add(MakeConstantString(CategoryName));
3608 Elements.add(MakeConstantString(ClassName));
3610 SmallVector<ObjCMethodDecl*, 16> InstanceMethods;
3611 InstanceMethods.insert(InstanceMethods.begin(), OCD->
instmeth_begin(),
3614 GenerateMethodList(ClassName, CategoryName, InstanceMethods,
false));
3618 SmallVector<ObjCMethodDecl*, 16> ClassMethods;
3621 Elements.add(GenerateMethodList(ClassName, CategoryName, ClassMethods,
true));
3624 Elements.add(GenerateCategoryProtocolList(CatDecl));
3626 const ObjCCategoryDecl *Category =
3630 Elements.add(GeneratePropertyList(OCD, Category,
false));
3632 Elements.add(GeneratePropertyList(OCD, Category,
true));
3634 Elements.addNullPointer(PtrTy);
3635 Elements.addNullPointer(PtrTy);
3639 Categories.push_back(Elements.finishAndCreateGlobal(
3640 std::string(
".objc_category_") + ClassName + CategoryName,
3644llvm::Constant *CGObjCGNU::GeneratePropertyList(
const Decl *Container,
3645 const ObjCContainerDecl *OCD,
3646 bool isClassProperty,
3647 bool protocolOptionalProperties) {
3649 SmallVector<const ObjCPropertyDecl *, 16> Properties;
3650 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
3654 std::function<void(
const ObjCProtocolDecl *Proto)> collectProtocolProperties
3655 = [&](
const ObjCProtocolDecl *Proto) {
3656 for (
const auto *P : Proto->protocols())
3657 collectProtocolProperties(P);
3658 for (
const auto *PD : Proto->properties()) {
3659 if (isClassProperty != PD->isClassProperty())
3667 Properties.push_back(PD);
3671 if (
const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
3673 for (
auto *PD : ClassExt->properties()) {
3674 if (isClassProperty != PD->isClassProperty())
3677 Properties.push_back(PD);
3681 if (isClassProperty != PD->isClassProperty())
3685 if (isProtocol && (protocolOptionalProperties != PD->isOptional()))
3692 Properties.push_back(PD);
3695 if (
const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
3697 collectProtocolProperties(P);
3698 else if (
const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD))
3699 for (
const auto *P : CD->protocols())
3700 collectProtocolProperties(P);
3702 auto numProperties = Properties.size();
3704 if (numProperties == 0)
3707 ConstantInitBuilder builder(CGM);
3708 auto propertyList = builder.beginStruct();
3709 auto properties = PushPropertyListHeader(propertyList, numProperties);
3713 for (
auto *property : Properties) {
3714 bool isSynthesized =
false;
3715 bool isDynamic =
false;
3719 isSynthesized = (propertyImpl->getPropertyImplementation() ==
3721 isDynamic = (propertyImpl->getPropertyImplementation() ==
3725 PushProperty(properties, property, Container, isSynthesized, isDynamic);
3727 properties.finishAndAddTo(propertyList);
3729 return propertyList.finishAndCreateGlobal(
".objc_property_list",
3733void CGObjCGNU::RegisterAlias(
const ObjCCompatibleAliasDecl *OAD) {
3735 ObjCInterfaceDecl *ClassDecl =
3741void CGObjCGNU::GenerateClass(
const ObjCImplementationDecl *OID) {
3745 const ObjCInterfaceDecl * SuperClassDecl =
3747 std::string SuperClassName;
3748 if (SuperClassDecl) {
3750 EmitClassRef(SuperClassName);
3754 ObjCInterfaceDecl *ClassDecl =
3760 std::string classSymbolName =
"__objc_class_name_" + ClassName;
3761 if (
auto *symbol = TheModule.getGlobalVariable(classSymbolName)) {
3762 symbol->setInitializer(llvm::ConstantInt::get(LongTy, 0));
3764 new llvm::GlobalVariable(TheModule, LongTy,
false,
3765 llvm::GlobalValue::ExternalLinkage,
3766 llvm::ConstantInt::get(LongTy, 0),
3776 SmallVector<llvm::Constant*, 16> IvarNames;
3777 SmallVector<llvm::Constant*, 16> IvarTypes;
3778 SmallVector<llvm::Constant*, 16> IvarOffsets;
3779 SmallVector<llvm::Constant*, 16> IvarAligns;
3780 SmallVector<Qualifiers::ObjCLifetime, 16> IvarOwnership;
3782 ConstantInitBuilder IvarOffsetBuilder(CGM);
3783 auto IvarOffsetValues = IvarOffsetBuilder.beginArray(PtrToIntTy);
3784 SmallVector<bool, 16> WeakIvars;
3785 SmallVector<bool, 16> StrongIvars;
3787 int superInstanceSize = !SuperClassDecl ? 0 :
3792 instanceSize = 0 - (instanceSize - superInstanceSize);
3798 IvarNames.push_back(MakeConstantString(IVD->getNameAsString()));
3800 std::string TypeStr;
3802 IvarTypes.push_back(MakeConstantString(TypeStr));
3803 IvarAligns.push_back(llvm::ConstantInt::get(IntTy,
3806 uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
3809 Offset = BaseOffset - superInstanceSize;
3811 llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset);
3813 std::string OffsetName =
"__objc_ivar_offset_value_" + ClassName +
"." +
3814 IVD->getNameAsString();
3816 llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName);
3818 OffsetVar->setInitializer(OffsetValue);
3822 OffsetVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
3824 OffsetVar =
new llvm::GlobalVariable(TheModule, Int32Ty,
3825 false, llvm::GlobalValue::ExternalLinkage,
3826 OffsetValue, OffsetName);
3827 IvarOffsets.push_back(OffsetValue);
3828 IvarOffsetValues.add(OffsetVar);
3830 IvarOwnership.push_back(lt);
3833 StrongIvars.push_back(
true);
3834 WeakIvars.push_back(
false);
3837 StrongIvars.push_back(
false);
3838 WeakIvars.push_back(
true);
3841 StrongIvars.push_back(
false);
3842 WeakIvars.push_back(
false);
3845 llvm::Constant *StrongIvarBitmap = MakeBitField(StrongIvars);
3846 llvm::Constant *WeakIvarBitmap = MakeBitField(WeakIvars);
3847 llvm::GlobalVariable *IvarOffsetArray =
3848 IvarOffsetValues.finishAndCreateGlobal(
".ivar.offsets",
3852 SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
3853 InstanceMethods.insert(InstanceMethods.begin(), OID->
instmeth_begin(),
3856 SmallVector<const ObjCMethodDecl*, 16> ClassMethods;
3860 llvm::Constant *Properties = GeneratePropertyList(OID, ClassDecl);
3863 auto RefProtocols = ClassDecl->
protocols();
3864 auto RuntimeProtocols =
3865 GetRuntimeProtocolList(RefProtocols.begin(), RefProtocols.end());
3866 SmallVector<std::string, 16> Protocols;
3867 for (
const auto *I : RuntimeProtocols)
3868 Protocols.push_back(I->getNameAsString());
3871 llvm::Constant *SuperClass;
3872 if (!SuperClassName.empty()) {
3873 SuperClass = MakeConstantString(SuperClassName,
".super_class_name");
3875 SuperClass = llvm::ConstantPointerNull::get(PtrToInt8Ty);
3878 llvm::Constant *MethodList = GenerateMethodList(ClassName,
"",
3879 InstanceMethods,
false);
3880 llvm::Constant *ClassMethodList = GenerateMethodList(ClassName,
"",
3881 ClassMethods,
true);
3882 llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
3883 IvarOffsets, IvarAligns, IvarOwnership);
3894 llvm::Type *IndexTy = Int32Ty;
3895 llvm::Constant *offsetPointerIndexes[] = {Zeros[0],
3896 llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 2 : 1),
nullptr,
3897 llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 3 : 2) };
3899 unsigned ivarIndex = 0;
3902 const std::string Name = GetIVarOffsetVariableName(ClassDecl, IVD);
3903 offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, ivarIndex);
3905 llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr(
3907 offsetPointerIndexes);
3909 llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name);
3911 offset->setInitializer(offsetValue);
3915 offset->setLinkage(llvm::GlobalValue::ExternalLinkage);
3918 new llvm::GlobalVariable(TheModule, offsetValue->getType(),
3919 false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name);
3922 llvm::Constant *ZeroPtr = llvm::ConstantInt::get(IntPtrTy, 0);
3925 llvm::Constant *MetaClassStruct = GenerateClassStructure(
3926 NULLPtr, NULLPtr, 0x12L, ClassName.c_str(),
nullptr, Zeros[0],
3927 NULLPtr, ClassMethodList, NULLPtr, NULLPtr,
3928 GeneratePropertyList(OID, ClassDecl,
true), ZeroPtr, ZeroPtr,
true);
3933 llvm::Constant *ClassStruct = GenerateClassStructure(
3934 MetaClassStruct, SuperClass, 0x11L, ClassName.c_str(),
nullptr,
3935 llvm::ConstantInt::getSigned(LongTy, instanceSize), IvarList, MethodList,
3936 GenerateProtocolList(Protocols), IvarOffsetArray, Properties,
3937 StrongIvarBitmap, WeakIvarBitmap);
3942 if (ClassPtrAlias) {
3943 ClassPtrAlias->replaceAllUsesWith(ClassStruct);
3944 ClassPtrAlias->eraseFromParent();
3945 ClassPtrAlias =
nullptr;
3947 if (MetaClassPtrAlias) {
3948 MetaClassPtrAlias->replaceAllUsesWith(MetaClassStruct);
3949 MetaClassPtrAlias->eraseFromParent();
3950 MetaClassPtrAlias =
nullptr;
3954 Classes.push_back(ClassStruct);
3957llvm::Function *CGObjCGNU::ModuleInitFunction() {
3959 if (Classes.empty() && Categories.empty() && ConstantStrings.empty() &&
3960 ExistingProtocols.empty() && SelectorTable.empty())
3964 GenerateProtocolHolderCategory();
3966 llvm::StructType *selStructTy = dyn_cast<llvm::StructType>(SelectorElemTy);
3969 { PtrToInt8Ty, PtrToInt8Ty });
3973 llvm::Constant *statics = NULLPtr;
3974 if (!ConstantStrings.empty()) {
3975 llvm::GlobalVariable *fileStatics = [&] {
3976 ConstantInitBuilder builder(CGM);
3977 auto staticsStruct = builder.beginStruct();
3980 if (stringClass.empty()) stringClass =
"NXConstantString";
3981 staticsStruct.add(MakeConstantString(stringClass,
3982 ".objc_static_class_name"));
3984 auto array = staticsStruct.beginArray();
3985 array.addAll(ConstantStrings);
3987 array.finishAndAddTo(staticsStruct);
3989 return staticsStruct.finishAndCreateGlobal(
".objc_statics",
3993 ConstantInitBuilder builder(CGM);
3994 auto allStaticsArray = builder.beginArray(fileStatics->getType());
3995 allStaticsArray.add(fileStatics);
3996 allStaticsArray.addNullPointer(fileStatics->getType());
3998 statics = allStaticsArray.finishAndCreateGlobal(
".objc_statics_ptr",
4004 SmallVector<llvm::GlobalAlias*, 16> selectorAliases;
4005 unsigned selectorCount;
4008 llvm::GlobalVariable *selectorList = [&] {
4009 ConstantInitBuilder builder(CGM);
4010 auto selectors = builder.beginArray(selStructTy);
4011 auto &table = SelectorTable;
4012 std::vector<Selector> allSelectors;
4013 for (
auto &entry : table)
4014 allSelectors.push_back(entry.first);
4015 llvm::sort(allSelectors);
4017 for (
auto &untypedSel : allSelectors) {
4018 std::string selNameStr = untypedSel.getAsString();
4019 llvm::Constant *selName = ExportUniqueString(selNameStr,
".objc_sel_name");
4021 for (TypedSelector &sel : table[untypedSel]) {
4022 llvm::Constant *selectorTypeEncoding = NULLPtr;
4023 if (!sel.first.empty())
4024 selectorTypeEncoding =
4025 MakeConstantString(sel.first,
".objc_sel_types");
4027 auto selStruct = selectors.beginStruct(selStructTy);
4028 selStruct.add(selName);
4029 selStruct.add(selectorTypeEncoding);
4030 selStruct.finishAndAddTo(selectors);
4033 selectorAliases.push_back(sel.second);
4038 selectorCount = selectors.size();
4044 auto selStruct = selectors.beginStruct(selStructTy);
4045 selStruct.add(NULLPtr);
4046 selStruct.add(NULLPtr);
4047 selStruct.finishAndAddTo(selectors);
4049 return selectors.finishAndCreateGlobal(
".objc_selector_list",
4054 for (
unsigned i = 0; i < selectorCount; ++i) {
4055 llvm::Constant *idxs[] = {
4057 llvm::ConstantInt::get(Int32Ty, i)
4060 llvm::Constant *selPtr = llvm::ConstantExpr::getGetElementPtr(
4061 selectorList->getValueType(), selectorList, idxs);
4062 selectorAliases[i]->replaceAllUsesWith(selPtr);
4063 selectorAliases[i]->eraseFromParent();
4066 llvm::GlobalVariable *symtab = [&] {
4067 ConstantInitBuilder builder(CGM);
4068 auto symtab = builder.beginStruct();
4071 symtab.addInt(LongTy, selectorCount);
4073 symtab.add(selectorList);
4076 symtab.addInt(CGM.
Int16Ty, Classes.size());
4078 symtab.addInt(CGM.
Int16Ty, Categories.size());
4081 auto classList = symtab.beginArray(PtrToInt8Ty);
4082 classList.addAll(Classes);
4083 classList.addAll(Categories);
4085 classList.add(statics);
4086 classList.add(NULLPtr);
4087 classList.finishAndAddTo(symtab);
4095 llvm::Constant *module = [&] {
4096 llvm::Type *moduleEltTys[] = {
4097 LongTy, LongTy, PtrToInt8Ty, symtab->getType(), IntTy
4099 llvm::StructType *moduleTy = llvm::StructType::get(
4101 ArrayRef(moduleEltTys).drop_back(
unsigned(RuntimeVersion < 10)));
4103 ConstantInitBuilder builder(CGM);
4104 auto module = builder.beginStruct(moduleTy);
4106 module.addInt(LongTy, RuntimeVersion);
4108 module.addInt(LongTy, CGM.getDataLayout().getTypeStoreSize(moduleTy));
4115 module.add(MakeConstantString(path, ".objc_source_file_name"));
4118 if (RuntimeVersion >= 10) {
4120 case LangOptions::GCOnly:
4121 module.addInt(IntTy, 2);
4123 case LangOptions::NonGC:
4125 module.addInt(IntTy, 1);
4127 module.addInt(IntTy, 0);
4129 case LangOptions::HybridGC:
4130 module.addInt(IntTy, 1);
4135 return module.finishAndCreateGlobal("", CGM.getPointerAlign());
4140 llvm::Function * LoadFunction = llvm::Function::Create(
4141 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
false),
4142 llvm::GlobalValue::InternalLinkage,
".objc_load_function",
4144 llvm::BasicBlock *EntryBB =
4145 llvm::BasicBlock::Create(VMContext,
"entry", LoadFunction);
4146 CGBuilderTy Builder(CGM, VMContext);
4147 Builder.SetInsertPoint(EntryBB);
4149 llvm::FunctionType *FT =
4150 llvm::FunctionType::get(Builder.getVoidTy(), module->getType(),
true);
4151 llvm::FunctionCallee Register =
4153 Builder.CreateCall(Register, module);
4155 if (!ClassAliases.empty()) {
4156 llvm::Type *ArgTypes[2] = {PtrTy, PtrToInt8Ty};
4157 llvm::FunctionType *RegisterAliasTy =
4158 llvm::FunctionType::get(Builder.getVoidTy(),
4160 llvm::Function *RegisterAlias = llvm::Function::Create(
4162 llvm::GlobalValue::ExternalWeakLinkage,
"class_registerAlias_np",
4164 llvm::BasicBlock *AliasBB =
4165 llvm::BasicBlock::Create(VMContext,
"alias", LoadFunction);
4166 llvm::BasicBlock *NoAliasBB =
4167 llvm::BasicBlock::Create(VMContext,
"no_alias", LoadFunction);
4170 llvm::Value *HasRegisterAlias = Builder.CreateICmpNE(RegisterAlias,
4171 llvm::Constant::getNullValue(RegisterAlias->getType()));
4172 Builder.CreateCondBr(HasRegisterAlias, AliasBB, NoAliasBB);
4175 Builder.SetInsertPoint(AliasBB);
4177 for (std::vector<ClassAliasPair>::iterator iter = ClassAliases.begin();
4178 iter != ClassAliases.end(); ++iter) {
4179 llvm::Constant *TheClass =
4180 TheModule.getGlobalVariable(
"_OBJC_CLASS_" + iter->first,
true);
4182 Builder.CreateCall(RegisterAlias,
4183 {TheClass, MakeConstantString(iter->second)});
4187 Builder.CreateBr(NoAliasBB);
4190 Builder.SetInsertPoint(NoAliasBB);
4192 Builder.CreateRetVoid();
4194 return LoadFunction;
4197llvm::Function *CGObjCGNU::GenerateMethod(
const ObjCMethodDecl *OMD,
4198 const ObjCContainerDecl *CD) {
4199 CodeGenTypes &Types = CGM.
getTypes();
4200 llvm::FunctionType *MethodTy =
4204 std::string FunctionName =
4205 getSymbolNameForMethod(OMD, !isDirect);
4208 return llvm::Function::Create(MethodTy,
4209 llvm::GlobalVariable::InternalLinkage,
4210 FunctionName, &TheModule);
4213 auto I = DirectMethodDefinitions.find(COMD);
4214 llvm::Function *OldFn =
nullptr, *
Fn =
nullptr;
4216 if (I == DirectMethodDefinitions.end()) {
4218 llvm::Function::Create(MethodTy, llvm::GlobalVariable::ExternalLinkage,
4219 FunctionName, &TheModule);
4220 DirectMethodDefinitions.insert(std::make_pair(COMD, F));
4237 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
"",
4239 Fn->takeName(OldFn);
4240 OldFn->replaceAllUsesWith(Fn);
4241 OldFn->eraseFromParent();
4248void CGObjCGNU::GenerateDirectMethodsPreconditionCheck(
4249 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
4250 const ObjCContainerDecl *CD) {
4252 "Direct method precondition checks not supported in GNU runtime yet");
4255void CGObjCGNU::GenerateDirectMethodPrologue(CodeGenFunction &CGF,
4257 const ObjCMethodDecl *OMD,
4258 const ObjCContainerDecl *CD) {
4260 "Direct method precondition checks not supported in GNU runtime yet");
4263llvm::FunctionCallee CGObjCGNU::GetPropertyGetFunction() {
4264 return GetPropertyFn;
4267llvm::FunctionCallee CGObjCGNU::GetPropertySetFunction() {
4268 return SetPropertyFn;
4271llvm::FunctionCallee CGObjCGNU::GetOptimizedPropertySetFunction(
bool atomic,
4276llvm::FunctionCallee CGObjCGNU::GetGetStructFunction() {
4277 return GetStructPropertyFn;
4280llvm::FunctionCallee CGObjCGNU::GetSetStructFunction() {
4281 return SetStructPropertyFn;
4284llvm::FunctionCallee CGObjCGNU::GetCppAtomicObjectGetFunction() {
4288llvm::FunctionCallee CGObjCGNU::GetCppAtomicObjectSetFunction() {
4292llvm::FunctionCallee CGObjCGNU::EnumerationMutationFunction() {
4293 return EnumerationMutationFn;
4296void CGObjCGNU::EmitSynchronizedStmt(CodeGenFunction &CGF,
4297 const ObjCAtSynchronizedStmt &S) {
4298 EmitAtSynchronizedStmt(CGF, S, SyncEnterFn, SyncExitFn);
4302void CGObjCGNU::EmitTryStmt(CodeGenFunction &CGF,
4303 const ObjCAtTryStmt &S) {
4315 EmitTryCatchStmt(CGF, S, EnterCatchFn, ExitCatchFn, ExceptionReThrowFn);
4318void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
4319 const ObjCAtThrowStmt &S,
4320 bool ClearInsertionPoint) {
4321 llvm::Value *ExceptionAsObject;
4322 bool isRethrow =
false;
4326 ExceptionAsObject = Exception;
4329 "Unexpected rethrow outside @catch block.");
4333 if (isRethrow && (usesSEHExceptions || usesCxxExceptions)) {
4342 Throw->setDoesNotReturn();
4344 ExceptionAsObject = CGF.
Builder.CreateBitCast(ExceptionAsObject, IdTy);
4345 llvm::CallBase *Throw =
4347 Throw->setDoesNotReturn();
4349 CGF.
Builder.CreateUnreachable();
4350 if (ClearInsertionPoint)
4351 CGF.
Builder.ClearInsertionPoint();
4354llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGenFunction &CGF,
4355 Address AddrWeakObj) {
4357 return B.CreateCall(
4358 WeakReadFn, EnforceType(B, AddrWeakObj.
emitRawPointer(CGF), PtrToIdTy));
4361void CGObjCGNU::EmitObjCWeakAssign(CodeGenFunction &CGF,
4362 llvm::Value *src, Address dst) {
4364 src = EnforceType(B, src, IdTy);
4365 llvm::Value *dstVal = EnforceType(B, dst.
emitRawPointer(CGF), PtrToIdTy);
4366 B.CreateCall(WeakAssignFn, {src, dstVal});
4369void CGObjCGNU::EmitObjCGlobalAssign(CodeGenFunction &CGF,
4370 llvm::Value *src, Address dst,
4373 src = EnforceType(B, src, IdTy);
4374 llvm::Value *dstVal = EnforceType(B, dst.
emitRawPointer(CGF), PtrToIdTy);
4376 assert(!threadlocal &&
"EmitObjCGlobalAssign - Threal Local API NYI");
4377 B.CreateCall(GlobalAssignFn, {src, dstVal});
4380void CGObjCGNU::EmitObjCIvarAssign(CodeGenFunction &CGF,
4381 llvm::Value *src, Address dst,
4382 llvm::Value *ivarOffset) {
4384 src = EnforceType(B, src, IdTy);
4385 llvm::Value *dstVal = EnforceType(B, dst.
emitRawPointer(CGF), IdTy);
4386 B.CreateCall(IvarAssignFn, {src, dstVal, ivarOffset});
4389void CGObjCGNU::EmitObjCStrongCastAssign(CodeGenFunction &CGF,
4390 llvm::Value *src, Address dst) {
4392 src = EnforceType(B, src, IdTy);
4393 llvm::Value *dstVal = EnforceType(B, dst.
emitRawPointer(CGF), PtrToIdTy);
4394 B.CreateCall(StrongCastAssignFn, {src, dstVal});
4397void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF,
4400 llvm::Value *Size) {
4402 llvm::Value *DestPtrVal = EnforceType(B, DestPtr.
emitRawPointer(CGF), PtrTy);
4403 llvm::Value *SrcPtrVal = EnforceType(B, SrcPtr.
emitRawPointer(CGF), PtrTy);
4405 B.CreateCall(MemMoveFn, {DestPtrVal, SrcPtrVal,
Size});
4408llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable(
4409 const ObjCInterfaceDecl *ID,
4410 const ObjCIvarDecl *Ivar) {
4411 const std::string Name = GetIVarOffsetVariableName(ID, Ivar);
4415 llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
4416 if (!IvarOffsetPointer)
4417 IvarOffsetPointer =
new llvm::GlobalVariable(
4418 TheModule, llvm::PointerType::getUnqual(VMContext),
false,
4419 llvm::GlobalValue::ExternalLinkage,
nullptr, Name);
4420 return IvarOffsetPointer;
4423LValue CGObjCGNU::EmitObjCValueForIvar(CodeGenFunction &CGF,
4425 llvm::Value *BaseValue,
4426 const ObjCIvarDecl *Ivar,
4427 unsigned CVRQualifiers) {
4428 const ObjCInterfaceDecl *
ID =
4429 ObjectTy->
castAs<ObjCObjectType>()->getInterface();
4430 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4431 EmitIvarOffset(CGF, ID, Ivar));
4450llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF,
4452 const ObjCIvarDecl *Ivar) {
4459 if (RuntimeVersion < 10 ||
4461 return CGF.
Builder.CreateZExtOrBitCast(
4465 llvm::PointerType::getUnqual(VMContext),
4466 ObjCIvarOffsetVariable(
Interface, Ivar),
4470 std::string
name =
"__objc_ivar_offset_value_" +
4473 llvm::Value *Offset = TheModule.getGlobalVariable(name);
4475 auto GV =
new llvm::GlobalVariable(TheModule, IntTy,
4476 false, llvm::GlobalValue::LinkOnceAnyLinkage,
4477 llvm::Constant::getNullValue(IntTy), name);
4482 if (Offset->getType() != PtrDiffTy)
4483 Offset = CGF.
Builder.CreateZExtOrBitCast(Offset, PtrDiffTy);
4487 return llvm::ConstantInt::get(PtrDiffTy, Offset,
true);
4493 switch (Runtime.getKind()) {
4495 if (Runtime.getVersion() >= VersionTuple(2, 0))
4496 return new CGObjCGNUstep2(CGM);
4497 return new CGObjCGNUstep(CGM);
4500 return new CGObjCGCC(CGM);
4503 return new CGObjCObjFW(CGM);
4509 llvm_unreachable(
"these runtimes are not GNU runtimes");
4511 llvm_unreachable(
"bad runtime");
Defines the clang::ASTContext interface.
static const ObjCInterfaceDecl * FindIvarInterface(ASTContext &Context, const ObjCInterfaceDecl *OID, const ObjCIvarDecl *OIVD)
static bool isNamed(const NamedDecl *ND, const char(&Str)[Len])
static StringRef getTriple(const Command &Job)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Defines the SourceManager interface.
Defines the Objective-C statement AST node classes.
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
void getObjCEncodingForType(QualType T, std::string &S, const FieldDecl *Field=nullptr, QualType *NotEncodedT=nullptr) const
Emit the Objective-CC type encoding for the given type T into S.
std::string getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, bool Extended=false) const
Emit the encoded type for the method declaration Decl into S.
std::string getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, const Decl *Container) const
getObjCEncodingForPropertyDecl - Return the encoded type for this method declaration.
const ASTRecordLayout & getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const
Get or compute information about the layout of the specified Objective-C interface.
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
ObjCPropertyImplDecl * getObjCPropertyImplDeclForPropertyDecl(const ObjCPropertyDecl *PD, const Decl *Container) const
QualType getObjCSelType() const
Retrieve the type that corresponds to the predefined Objective-C 'SEL' type.
QualType getObjCIdType() const
Represents the Objective-CC id type.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
void getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT, QualType T, std::string &S, bool Extended) const
getObjCEncodingForMethodParameter - Return the encoded type for a single method parameter or return t...
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
uint64_t getCharWidth() const
Return the size of the character type, in bits.
CharUnits getSize() const
getSize - Get the record size in characters.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::LoadInst * CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, CharUnits Align, const llvm::Twine &Name="")
virtual llvm::Constant * getAddrOfRTTIDescriptor(QualType Ty)=0
virtual CatchTypeInfo getCatchAllTypeInfo()
Implements runtime-specific code generation functions.
void add(RValue rvalue, QualType type)
void addFrom(const CallArgList &other)
Add all the arguments from another CallArgList to this one.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
llvm::CallBase * EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args, const Twine &name="")
Emits a call or invoke instruction to the given runtime function.
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
llvm::Value * EmitObjCThrowOperand(const Expr *expr)
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
JumpDest ReturnBlock
ReturnBlock - Unified return block.
llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)
CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
llvm::Value * LoadObjCSelf()
LoadObjCSelf - Load the value of self.
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
SmallVector< llvm::Value *, 8 > ObjCEHValueStack
ObjCEHValueStack - Stack of Objective-C exception values, used for rethrows.
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
static bool hasAggregateEvaluationKind(QualType T)
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
llvm::LLVMContext & getLLVMContext()
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
This class organizes the cross-function state that is used while generating LLVM code.
void setGVProperties(llvm::GlobalValue *GV, GlobalDecl GD) const
Set visibility, dllimport/dllexport and dso_local.
llvm::Module & getModule() const
llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)
Create or return a runtime function declaration with the specified type and name.
void addCompilerUsedGlobal(llvm::GlobalValue *GV)
Add a global to a list to be added to the llvm.compiler.used metadata.
bool ReturnTypeUsesFPRet(QualType ResultType)
Return true iff the given type uses 'fpret' when used as a return type.
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const TargetInfo & getTarget() const
void addUsedGlobal(llvm::GlobalValue *GV)
Add a global to a list to be added to the llvm.used metadata.
const llvm::DataLayout & getDataLayout() const
CGCXXABI & getCXXABI() const
const llvm::Triple & getTriple() const
bool ReturnTypeHasInReg(const CGFunctionInfo &FI)
Return true iff the given type has inreg set.
ASTContext & getContext() const
bool ReturnTypeUsesSRet(const CGFunctionInfo &FI)
Return true iff the given type uses 'sret' when used as a return type.
const CodeGenOptions & getCodeGenOpts() const
llvm::LLVMContext & getLLVMContext()
llvm::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
ConstantAddress GetAddrOfConstantCString(const std::string &Str, StringRef GlobalName=".str")
Returns a pointer to a character array containing the literal and a terminating '\0' character.
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
const CGFunctionInfo & arrangeObjCMethodDeclaration(const ObjCMethodDecl *MD)
Objective-C methods are C functions with some implicit parameters.
bool isZeroInitializable(QualType T)
IsZeroInitializable - Return whether a type can be zero-initialized (in the C++ sense) with an LLVM z...
llvm::Constant * getPointer() const
void add(llvm::Constant *value)
Add a new value to this initializer.
void addInt(llvm::IntegerType *intTy, uint64_t value, bool isSigned=false)
Add an integer value of a specific type.
void addNullPointer(llvm::PointerType *ptrTy)
Add a null pointer of a specific type.
ArrayBuilder beginArray(llvm::Type *eltTy=nullptr)
llvm::GlobalVariable * finishAndCreateGlobal(As &&...args)
Given that this builder was created by beginning an array or struct directly on a ConstantInitBuilder...
StructBuilder beginStruct(llvm::StructType *ty=nullptr)
void finishAndAddTo(AggregateBuilderBase &parent)
Given that this builder was created by beginning an array or struct component on the given parent bui...
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
Address getAggregateAddress() const
getAggregateAddr() - Return the Value* of the address of the aggregate.
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
llvm::Value * getPointer() const
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
bool isWeakImported() const
Determine whether this is a weak-imported symbol.
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
StringRef getName() const
The name of this FileEntry.
DirectoryEntryRef getDir() const
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
clang::ObjCRuntime ObjCRuntime
std::string ObjCConstantStringClass
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Visibility getVisibility() const
Determines the visibility of this entity.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
const Expr * getThrowExpr() const
const ObjCProtocolList & getReferencedProtocols() const
ObjCCategoryDecl * getCategoryDecl() const
const ObjCInterfaceDecl * getClassInterface() const
classmeth_iterator classmeth_end() const
classmeth_iterator classmeth_begin() const
instmeth_range instance_methods() const
instmeth_iterator instmeth_end() const
instmeth_iterator instmeth_begin() const
prop_range properties() const
classmeth_range class_methods() const
propimpl_range property_impls() const
const ObjCInterfaceDecl * getClassInterface() const
Represents an ObjC class declaration.
all_protocol_iterator all_referenced_protocol_end() const
all_protocol_range all_referenced_protocols() const
ObjCIvarDecl * all_declared_ivar_begin()
all_declared_ivar_begin - return first ivar declared in this class, its extensions and its implementa...
protocol_range protocols() const
all_protocol_iterator all_referenced_protocol_begin() const
ObjCInterfaceDecl * getSuperClass() const
ObjCInterfaceDecl * getDefinition()
Retrieve the definition of this class, or NULL if this class has been forward-declared (with @class) ...
known_extensions_range known_extensions() const
ObjCInterfaceDecl * getDecl() const
Get the declaration of this interface.
ObjCIvarDecl - Represents an ObjC instance variable.
AccessControl getAccessControl() const
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
ObjCIvarDecl * getNextIvar()
ImplicitParamDecl * getSelfDecl() const
Stmt * getBody() const override
Retrieve the body of this method, if it has one.
ObjCMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
bool isDirectMethod() const
True if the method is tagged as objc_direct.
Selector getSelector() const
ImplicitParamDecl * getCmdDecl() const
QualType getReturnType() const
bool isClassMethod() const
const ObjCObjectType * getObjectType() const
Gets the type pointed to by this ObjC pointer.
const ObjCInterfaceType * getInterfaceType() const
If this pointer points to an Objective C @interface type, gets the type for that interface.
ObjCMethodDecl * getGetterMethodDecl() const
ObjCMethodDecl * getSetterMethodDecl() const
ObjCProtocolDecl * getDefinition()
Retrieve the definition of this protocol, if any.
bool isNonRuntimeProtocol() const
This is true iff the protocol is tagged with the objc_non_runtime_protocol attribute.
protocol_iterator protocol_begin() const
protocol_range protocols() const
protocol_iterator protocol_end() const
const VersionTuple & getVersion() const
bool isNonFragile() const
Does this runtime follow the set of implied behaviors for a "non-fragile" ABI?
Kind
The basic Objective-C runtimes that we know about.
@ MacOSX
'macosx' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the non-fragile AB...
@ FragileMacOSX
'macosx-fragile' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the fragil...
@ GNUstep
'gnustep' is the modern non-fragile GNUstep runtime.
@ ObjFW
'objfw' is the Objective-C runtime included in ObjFW
@ iOS
'ios' is the Apple-provided NeXT-derived runtime on iOS or the iOS simulator; it is always non-fragil...
@ GCC
'gcc' is the Objective-C runtime shipped with GCC, implementing a fragile Objective-C ABI
@ WatchOS
'watchos' is a variant of iOS for Apple's watchOS.
A (possibly-)qualified type.
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
@ OCL_None
There is no lifetime qualification on this type.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
std::string getAsString() const
Derive the full selector name (e.g.
bool containsNonAscii() const
unsigned getLength() const
uint32_t getCodeUnit(size_t i) const
StringRef getString() const
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
static DeclContext * castToDeclContext(const TranslationUnitDecl *D)
const T * castAs() const
Member-template castAs<specific type>.
bool isObjCQualifiedIdType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isObjCIdType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool hasPointerRepresentation() const
Whether this type is represented natively as a pointer.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
CGObjCRuntime * CreateGNUObjCRuntime(CodeGenModule &CGM)
Creates an instance of an Objective-C runtime class.
StringRef getName(const HeaderType T)
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
@ Address
A pointer to a ValueDecl.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Result
The result type of a method or function.
Selector GetNullarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing a nullary selector.
@ Type
The name was classified as a type.
U cast(CodeGen::Address addr)
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
@ Class
The "class" keyword introduces the elaborated-type-specifier.
@ HiddenVisibility
Objects with "hidden" visibility are not seen by the dynamic linker.
int const char * function
CharUnits getIntAlign() const
llvm::IntegerType * Int16Ty
llvm::PointerType * Int8PtrTy
CharUnits getPointerAlign() const