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", VoidTy);
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 int64_t Offset =
static_cast<int64_t>(BaseOffset) - superInstanceSize;
1889 llvm::Constant *OffsetValue =
1890 llvm::ConstantInt::getSigned(IntTy, Offset);
1891 std::string OffsetName = GetIVarOffsetVariableName(classDecl, IVD);
1892 llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName);
1894 OffsetVar->setInitializer(OffsetValue);
1896 OffsetVar =
new llvm::GlobalVariable(TheModule, IntTy,
1897 false, llvm::GlobalValue::ExternalLinkage,
1898 OffsetValue, OffsetName);
1899 auto ivarVisibility =
1903 llvm::GlobalValue::HiddenVisibility :
1904 llvm::GlobalValue::DefaultVisibility;
1905 OffsetVar->setVisibility(ivarVisibility);
1906 if (ivarVisibility != llvm::GlobalValue::HiddenVisibility)
1908 ivarBuilder.add(OffsetVar);
1910 ivarBuilder.addInt(Int32Ty,
1921 ivarBuilder.addInt(Int32Ty,
1922 (align << 3) | (1<<2) |
1923 FlagsForOwnership(ivarTy.getQualifiers().getObjCLifetime()));
1924 ivarBuilder.finishAndAddTo(ivarArrayBuilder);
1926 ivarArrayBuilder.finishAndAddTo(ivarListBuilder);
1927 auto ivarList = ivarListBuilder.finishAndCreateGlobal(
".objc_ivar_list",
1929 llvm::GlobalValue::PrivateLinkage);
1930 classFields.add(ivarList);
1933 SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
1934 InstanceMethods.insert(InstanceMethods.begin(), OID->
instmeth_begin(),
1937 if (propImpl->getPropertyImplementation() ==
1939 auto addIfExists = [&](
const ObjCMethodDecl *OMD) {
1940 if (OMD && OMD->hasBody())
1941 InstanceMethods.push_back(OMD);
1943 addIfExists(propImpl->getGetterMethodDecl());
1944 addIfExists(propImpl->getSetterMethodDecl());
1947 if (InstanceMethods.size() == 0)
1948 classFields.addNullPointer(PtrTy);
1951 GenerateMethodList(className,
"", InstanceMethods,
false));
1954 classFields.addNullPointer(PtrTy);
1956 classFields.addNullPointer(PtrTy);
1958 classFields.addNullPointer(PtrTy);
1960 classFields.addNullPointer(PtrTy);
1962 classFields.addNullPointer(PtrTy);
1964 auto RuntimeProtocols =
1967 SmallVector<llvm::Constant *, 16> Protocols;
1968 for (
const auto *I : RuntimeProtocols)
1969 Protocols.push_back(GenerateProtocolRef(I));
1971 if (Protocols.empty())
1972 classFields.addNullPointer(PtrTy);
1974 classFields.add(GenerateProtocolList(Protocols));
1976 classFields.addNullPointer(PtrTy);
1978 classFields.addInt(LongTy, 0);
1980 classFields.add(GeneratePropertyList(OID, classDecl));
1982 llvm::GlobalVariable *classStruct =
1983 classFields.finishAndCreateGlobal(SymbolForClass(className),
1986 auto *classRefSymbol = GetClassVar(className);
1987 classRefSymbol->setSection(sectionName<ClassReferenceSection>());
1988 classRefSymbol->setInitializer(classStruct);
1993 classStruct->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
1998 std::pair<llvm::GlobalVariable*, int> v{classStruct, 1};
1999 EarlyInitList.emplace_back(std::string(SuperClass->getName()),
2008 if (ClassPtrAlias) {
2009 ClassPtrAlias->replaceAllUsesWith(classStruct);
2010 ClassPtrAlias->eraseFromParent();
2011 ClassPtrAlias =
nullptr;
2013 if (
auto Placeholder =
2014 TheModule.getNamedGlobal(SymbolForClass(className)))
2015 if (Placeholder != classStruct) {
2016 Placeholder->replaceAllUsesWith(classStruct);
2017 Placeholder->eraseFromParent();
2018 classStruct->setName(SymbolForClass(className));
2020 if (MetaClassPtrAlias) {
2021 MetaClassPtrAlias->replaceAllUsesWith(metaclass);
2022 MetaClassPtrAlias->eraseFromParent();
2023 MetaClassPtrAlias =
nullptr;
2025 assert(classStruct->getName() == SymbolForClass(className));
2027 auto classInitRef =
new llvm::GlobalVariable(TheModule,
2028 classStruct->getType(),
false, llvm::GlobalValue::ExternalLinkage,
2029 classStruct, ManglePublicSymbol(
"OBJC_INIT_CLASS_") + className);
2030 classInitRef->setSection(sectionName<ClassSection>());
2033 EmittedClass =
true;
2036 CGObjCGNUstep2(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 10, 4, 2) {
2037 MsgLookupSuperFn.init(&CGM,
"objc_msg_lookup_super", IMPTy,
2038 PtrToObjCSuperTy, SelectorTy);
2039 SentInitializeFn.init(&CGM,
"objc_send_initialize",
2040 llvm::Type::getVoidTy(VMContext), IdTy);
2049 PropertyMetadataTy =
2051 { PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
2054 void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
2055 const ObjCMethodDecl *OMD,
2056 const ObjCContainerDecl *CD)
override {
2058 bool ReceiverCanBeNull =
true;
2060 auto selfValue = Builder.CreateLoad(selfAddr);
2085 ReceiverCanBeNull = isWeakLinkedClass(OID);
2089 if (ReceiverCanBeNull) {
2090 llvm::BasicBlock *SelfIsNilBlock =
2092 llvm::BasicBlock *ContBlock =
2097 auto Zero = llvm::ConstantPointerNull::get(selfTy);
2099 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue,
Zero),
2100 SelfIsNilBlock, ContBlock,
2101 MDHelper.createUnlikelyBranchWeights());
2107 Builder.SetInsertPoint(SelfIsNilBlock);
2108 if (!retTy->isVoidType()) {
2116 Builder.SetInsertPoint(ContBlock);
2122 llvm::StructType::get(PtrTy, PtrTy, PtrTy, LongTy, LongTy);
2129 llvm::Value *Val = Builder.CreateStructGEP(classStart, selfValue, 4);
2131 astContext.getTypeAlign(astContext.UnsignedLongTy));
2132 auto flags = Builder.CreateLoad(Address{Val, LongTy, Align});
2133 auto isInitialized =
2134 Builder.CreateAnd(flags, ClassFlags::ClassFlagInitialized);
2135 llvm::BasicBlock *notInitializedBlock =
2137 llvm::BasicBlock *initializedBlock =
2139 Builder.CreateCondBr(Builder.CreateICmpEQ(isInitialized, Zeros[0]),
2140 notInitializedBlock, initializedBlock,
2141 MDHelper.createUnlikelyBranchWeights());
2143 Builder.SetInsertPoint(notInitializedBlock);
2145 Builder.CreateBr(initializedBlock);
2147 Builder.SetInsertPoint(initializedBlock);
2155 Builder.CreateStore(GetSelector(CGF, OMD),
2161const char *
const CGObjCGNUstep2::SectionsBaseNames[8] =
2168"__objc_protocol_refs",
2169"__objc_class_aliases",
2170"__objc_constant_string"
2173const char *
const CGObjCGNUstep2::PECOFFSectionsBaseNames[8] =
2186class CGObjCObjFW:
public CGObjCGNU {
2190 LazyRuntimeFunction MsgLookupFn;
2193 LazyRuntimeFunction MsgLookupFnSRet;
2197 LazyRuntimeFunction MsgLookupSuperFn, MsgLookupSuperFnSRet;
2199 llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver,
2200 llvm::Value *cmd, llvm::MDNode *node,
2201 MessageSendInfo &MSI)
override {
2202 CGBuilderTy &Builder = CGF.
Builder;
2203 llvm::Value *args[] = {
2204 EnforceType(Builder, Receiver, IdTy),
2205 EnforceType(Builder, cmd, SelectorTy) };
2207 llvm::CallBase *imp;
2213 imp->setMetadata(msgSendMDKind, node);
2217 llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
2218 llvm::Value *cmd, MessageSendInfo &MSI)
override {
2219 CGBuilderTy &Builder = CGF.
Builder;
2220 llvm::Value *lookupArgs[] = {
2221 EnforceType(Builder, ObjCSuper.
emitRawPointer(CGF), PtrToObjCSuperTy),
2231 llvm::Value *GetClassNamed(CodeGenFunction &CGF,
const std::string &Name,
2232 bool isWeak)
override {
2234 return CGObjCGNU::GetClassNamed(CGF, Name, isWeak);
2237 std::string SymbolName =
"_OBJC_CLASS_" + Name;
2238 llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(SymbolName);
2240 ClassSymbol =
new llvm::GlobalVariable(TheModule, LongTy,
false,
2241 llvm::GlobalValue::ExternalLinkage,
2242 nullptr, SymbolName);
2246 void GenerateDirectMethodPrologue(
2247 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
2248 const ObjCContainerDecl *CD)
override {
2250 bool ReceiverCanBeNull =
true;
2252 auto selfValue = Builder.CreateLoad(selfAddr);
2271 "GenerateDirectMethod() should be called with the Class Interface");
2284 result = GeneratePossiblySpecializedMessageSend(
2285 CGF, ReturnValueSlot(), ResultType, SelfSel, selfValue, Args, OID,
2292 ReceiverCanBeNull = isWeakLinkedClass(OID);
2295 if (ReceiverCanBeNull) {
2296 llvm::BasicBlock *SelfIsNilBlock =
2298 llvm::BasicBlock *ContBlock =
2303 auto Zero = llvm::ConstantPointerNull::get(selfTy);
2306 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue,
Zero),
2307 SelfIsNilBlock, ContBlock,
2308 MDHelper.createUnlikelyBranchWeights());
2314 Builder.SetInsertPoint(SelfIsNilBlock);
2315 if (!retTy->isVoidType()) {
2323 Builder.SetInsertPoint(ContBlock);
2331 Builder.CreateStore(GetSelector(CGF, OMD),
2337 CGObjCObjFW(CodeGenModule &Mod): CGObjCGNU(Mod, 9, 3) {
2339 MsgLookupFn.init(&CGM,
"objc_msg_lookup", IMPTy, IdTy, SelectorTy);
2340 MsgLookupFnSRet.init(&CGM,
"objc_msg_lookup_stret", IMPTy, IdTy,
2343 MsgLookupSuperFn.init(&CGM,
"objc_msg_lookup_super", IMPTy,
2344 PtrToObjCSuperTy, SelectorTy);
2345 MsgLookupSuperFnSRet.init(&CGM,
"objc_msg_lookup_super_stret", IMPTy,
2346 PtrToObjCSuperTy, SelectorTy);
2354void CGObjCGNU::EmitClassRef(
const std::string &className) {
2355 std::string symbolRef =
"__objc_class_ref_" + className;
2357 if (TheModule.getGlobalVariable(symbolRef))
2359 std::string symbolName =
"__objc_class_name_" + className;
2360 llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName);
2362 ClassSymbol =
new llvm::GlobalVariable(TheModule, LongTy,
false,
2363 llvm::GlobalValue::ExternalLinkage,
2364 nullptr, symbolName);
2366 new llvm::GlobalVariable(TheModule, ClassSymbol->getType(),
true,
2367 llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef);
2370CGObjCGNU::CGObjCGNU(CodeGenModule &cgm,
unsigned runtimeABIVersion,
2371 unsigned protocolClassVersion,
unsigned classABI)
2372 : CGObjCRuntime(cgm), TheModule(CGM.getModule()),
2373 VMContext(cgm.getLLVMContext()), ClassPtrAlias(
nullptr),
2374 MetaClassPtrAlias(
nullptr), RuntimeVersion(runtimeABIVersion),
2375 ProtocolVersion(protocolClassVersion), ClassABIVersion(classABI) {
2379 msgSendMDKind = VMContext.getMDKindID(
"GNUObjCMessageSend");
2380 usesSEHExceptions = Triple.isWindowsMSVCEnvironment();
2396 Int8Ty = llvm::Type::getInt8Ty(VMContext);
2401 PtrToInt8Ty = PtrTy;
2402 ProtocolPtrTy = PtrTy;
2404 Zeros[0] = llvm::ConstantInt::get(LongTy, 0);
2405 Zeros[1] = Zeros[0];
2406 NULLPtr = llvm::ConstantPointerNull::get(PtrToInt8Ty);
2410 SelectorTy = PtrToInt8Ty;
2411 SelectorElemTy = Int8Ty;
2417 Int32Ty = llvm::Type::getInt32Ty(VMContext);
2418 Int64Ty = llvm::Type::getInt64Ty(VMContext);
2421 CGM.
getDataLayout().getPointerSizeInBits() == 32 ? Int32Ty : Int64Ty;
2436 ProtocolTy = llvm::StructType::get(IdTy,
2458 PropertyMetadataTy = llvm::StructType::get(CGM.
getLLVMContext(), {
2459 PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty,
2460 PtrToInt8Ty, PtrToInt8Ty });
2462 ObjCSuperTy = llvm::StructType::get(IdTy, IdTy);
2463 PtrToObjCSuperTy = PtrTy;
2465 llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
2468 ExceptionThrowFn.init(&CGM,
"objc_exception_throw", VoidTy, IdTy);
2469 ExceptionReThrowFn.init(&CGM,
2470 usesCxxExceptions ?
"objc_exception_rethrow"
2471 :
"objc_exception_throw",
2474 SyncEnterFn.init(&CGM,
"objc_sync_enter", IntTy, IdTy);
2476 SyncExitFn.init(&CGM,
"objc_sync_exit", IntTy, IdTy);
2479 EnumerationMutationFn.init(&CGM,
"objc_enumerationMutation", VoidTy, IdTy);
2482 GetPropertyFn.init(&CGM,
"objc_getProperty", IdTy, IdTy, SelectorTy,
2485 SetPropertyFn.init(&CGM,
"objc_setProperty", VoidTy, IdTy, SelectorTy,
2486 PtrDiffTy, IdTy, BoolTy, BoolTy);
2488 GetStructPropertyFn.init(&CGM,
"objc_getPropertyStruct", VoidTy, PtrTy, PtrTy,
2489 PtrDiffTy, BoolTy, BoolTy);
2491 SetStructPropertyFn.init(&CGM,
"objc_setPropertyStruct", VoidTy, PtrTy, PtrTy,
2492 PtrDiffTy, BoolTy, BoolTy);
2499 RuntimeVersion = 10;
2514 IvarAssignFn.init(&CGM,
"objc_assign_ivar", IdTy, IdTy, IdTy, PtrDiffTy);
2516 StrongCastAssignFn.init(&CGM,
"objc_assign_strongCast", IdTy, IdTy,
2519 GlobalAssignFn.init(&CGM,
"objc_assign_global", IdTy, IdTy, PtrToIdTy);
2521 WeakAssignFn.init(&CGM,
"objc_assign_weak", IdTy, IdTy, PtrToIdTy);
2523 WeakReadFn.init(&CGM,
"objc_read_weak", IdTy, PtrToIdTy);
2525 MemMoveFn.init(&CGM,
"objc_memmove_collectable", PtrTy, PtrTy, PtrTy,
2531 const std::string &Name,
bool isWeak) {
2532 llvm::Constant *ClassName = MakeConstantString(Name);
2544 llvm::FunctionType::get(IdTy, PtrToInt8Ty,
true),
"objc_lookup_class");
2550llvm::Value *CGObjCGNU::GetClass(CodeGenFunction &CGF,
2551 const ObjCInterfaceDecl *OID) {
2554 if (
auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(
Value))
2559llvm::Value *CGObjCGNU::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
2560 auto *
Value = GetClassNamed(CGF,
"NSAutoreleasePool",
false);
2561 if (CGM.
getTriple().isOSBinFormatCOFF()) {
2562 if (
auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(
Value)) {
2567 const VarDecl *VD =
nullptr;
2569 if ((VD = dyn_cast<VarDecl>(
Result)))
2578llvm::Value *CGObjCGNU::GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
2579 const std::string &TypeEncoding) {
2580 SmallVectorImpl<TypedSelector> &Types = SelectorTable[Sel];
2581 llvm::GlobalAlias *SelValue =
nullptr;
2583 for (
const TypedSelector &
Type : Types) {
2584 if (
Type.first == TypeEncoding) {
2585 SelValue =
Type.second;
2590 SelValue = llvm::GlobalAlias::create(SelectorElemTy, 0,
2591 llvm::GlobalValue::PrivateLinkage,
2594 Types.emplace_back(TypeEncoding, SelValue);
2600Address CGObjCGNU::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
2601 llvm::Value *SelValue = GetSelector(CGF, Sel);
2611llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel) {
2612 return GetTypedSelector(CGF, Sel, std::string());
2615llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF,
2616 const ObjCMethodDecl *
Method) {
2618 return GetTypedSelector(CGF,
Method->getSelector(), SelTypes);
2621llvm::Constant *CGObjCGNU::GetEHType(QualType
T) {
2628 return MakeConstantString(
"@id");
2635 const ObjCObjectPointerType *OPT =
T->
getAs<ObjCObjectPointerType>();
2636 assert(OPT &&
"Invalid @catch type.");
2637 const ObjCInterfaceDecl *IDecl = OPT->
getObjectType()->getInterface();
2638 assert(IDecl &&
"Invalid @catch type.");
2642llvm::Constant *CGObjCGNUstep::GetEHType(QualType
T) {
2643 if (usesSEHExceptions)
2646 if (!CGM.
getLangOpts().CPlusPlus && !usesCxxExceptions)
2647 return CGObjCGNU::GetEHType(
T);
2655 llvm::Constant *IDEHType =
2656 CGM.
getModule().getGlobalVariable(
"__objc_id_type_info");
2659 new llvm::GlobalVariable(CGM.
getModule(), PtrToInt8Ty,
2661 llvm::GlobalValue::ExternalLinkage,
2662 nullptr,
"__objc_id_type_info");
2666 const ObjCObjectPointerType *PT =
2667 T->
getAs<ObjCObjectPointerType>();
2668 assert(PT &&
"Invalid @catch type.");
2670 assert(IT &&
"Invalid @catch type.");
2671 std::string className =
2674 std::string typeinfoName =
"__objc_eh_typeinfo_" + className;
2677 if (llvm::Constant *typeinfo = TheModule.getGlobalVariable(typeinfoName))
2685 const char *vtableName =
"_ZTVN7gnustep7libobjc22__objc_class_type_infoE";
2686 auto *Vtable = TheModule.getGlobalVariable(vtableName);
2688 Vtable =
new llvm::GlobalVariable(TheModule, PtrToInt8Ty,
true,
2689 llvm::GlobalValue::ExternalLinkage,
2690 nullptr, vtableName);
2692 llvm::Constant *Two = llvm::ConstantInt::get(IntTy, 2);
2694 llvm::ConstantExpr::getGetElementPtr(Vtable->getValueType(), Vtable, Two);
2696 llvm::Constant *typeName =
2697 ExportUniqueString(className,
"__objc_eh_typename_");
2699 ConstantInitBuilder builder(CGM);
2700 auto fields = builder.beginStruct();
2701 fields.add(BVtable);
2702 fields.add(typeName);
2703 llvm::Constant *TI =
2704 fields.finishAndCreateGlobal(
"__objc_eh_typeinfo_" + className,
2707 llvm::GlobalValue::LinkOnceODRLinkage);
2712ConstantAddress CGObjCGNU::GenerateConstantString(
const StringLiteral *SL) {
2714 std::string Str = SL->
getString().str();
2718 llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
2719 if (old != ObjCStrings.end())
2720 return ConstantAddress(old->getValue(), Int8Ty, Align);
2724 if (StringClass.empty()) StringClass =
"NSConstantString";
2726 std::string Sym =
"_OBJC_CLASS_";
2729 llvm::Constant *
isa = TheModule.getNamedGlobal(Sym);
2732 isa =
new llvm::GlobalVariable(TheModule, IdTy,
false,
2733 llvm::GlobalValue::ExternalWeakLinkage,
2736 ConstantInitBuilder Builder(CGM);
2737 auto Fields = Builder.beginStruct();
2739 Fields.
add(MakeConstantString(Str));
2740 Fields.
addInt(IntTy, Str.size());
2742 ObjCStrings[Str] = ObjCStr;
2743 ConstantStrings.push_back(ObjCStr);
2744 return ConstantAddress(ObjCStr, Int8Ty, Align);
2747ConstantAddress CGObjCGNU::GenerateConstantNumber(
const bool Value,
2748 const QualType &Ty) {
2749 llvm_unreachable(
"Method should not be called, no GNU runtimes provide these "
2750 "or support ObjC number literal constant initializers");
2753ConstantAddress CGObjCGNU::GenerateConstantNumber(
const llvm::APSInt &
Value,
2754 const QualType &Ty) {
2755 llvm_unreachable(
"Method should not be called, no GNU runtimes provide these "
2756 "or support ObjC number literal constant initializers");
2759ConstantAddress CGObjCGNU::GenerateConstantNumber(
const llvm::APFloat &
Value,
2760 const QualType &Ty) {
2761 llvm_unreachable(
"Method should not be called, no GNU runtimes provide these "
2762 "or support ObjC number literal constant initializers");
2766CGObjCGNU::GenerateConstantArray(
const ArrayRef<llvm::Constant *> &Objects) {
2767 llvm_unreachable(
"Method should not be called, no GNU runtimes provide these "
2768 "or support ObjC array literal constant initializers");
2771ConstantAddress CGObjCGNU::GenerateConstantDictionary(
2772 const ObjCDictionaryLiteral *E,
2773 ArrayRef<std::pair<llvm::Constant *, llvm::Constant *>> KeysAndObjects) {
2774 llvm_unreachable(
"Method should not be called, no GNU runtimes provide these "
2775 "or support ObjC dictionary literal constant initializers");
2782CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF,
2783 ReturnValueSlot Return,
2784 QualType ResultType,
2786 const ObjCInterfaceDecl *
Class,
2787 bool isCategoryImpl,
2788 llvm::Value *Receiver,
2789 bool IsClassMessage,
2790 const CallArgList &CallArgs,
2791 const ObjCMethodDecl *
Method) {
2792 CGBuilderTy &Builder = CGF.
Builder;
2793 if (CGM.
getLangOpts().getGC() == LangOptions::GCOnly) {
2794 if (Sel == RetainSel || Sel == AutoreleaseSel) {
2798 if (Sel == ReleaseSel) {
2803 llvm::Value *cmd = GetSelector(CGF, Sel);
2804 CallArgList ActualArgs;
2806 ActualArgs.
add(
RValue::get(EnforceType(Builder, Receiver, IdTy)), ASTIdTy);
2810 MessageSendInfo MSI = getMessageSendInfo(
Method, ResultType, ActualArgs);
2812 llvm::Value *ReceiverClass =
nullptr;
2815 ReceiverClass = GetClassNamed(CGF,
2816 Class->getSuperClass()->getNameAsString(),
false);
2817 if (IsClassMessage) {
2820 Builder.CreateAlignedLoad(IdTy, ReceiverClass, CGF.
getPointerAlign());
2822 ReceiverClass = EnforceType(Builder, ReceiverClass, IdTy);
2824 if (isCategoryImpl) {
2825 llvm::FunctionCallee classLookupFunction =
nullptr;
2826 if (IsClassMessage) {
2828 IdTy, PtrTy,
true),
"objc_get_meta_class");
2831 IdTy, PtrTy,
true),
"objc_get_class");
2833 ReceiverClass = Builder.CreateCall(classLookupFunction,
2834 MakeConstantString(
Class->getNameAsString()));
2841 if (IsClassMessage) {
2842 if (!MetaClassPtrAlias) {
2843 MetaClassPtrAlias = llvm::GlobalAlias::create(
2844 IdElemTy, 0, llvm::GlobalValue::InternalLinkage,
2845 ".objc_metaclass_ref" +
Class->getNameAsString(), &TheModule);
2847 ReceiverClass = MetaClassPtrAlias;
2849 if (!ClassPtrAlias) {
2850 ClassPtrAlias = llvm::GlobalAlias::create(
2851 IdElemTy, 0, llvm::GlobalValue::InternalLinkage,
2852 ".objc_class_ref" +
Class->getNameAsString(), &TheModule);
2854 ReceiverClass = ClassPtrAlias;
2858 llvm::Type *CastTy = llvm::StructType::get(IdTy, IdTy);
2860 ReceiverClass = Builder.CreateStructGEP(CastTy, ReceiverClass, 1);
2863 Builder.CreateAlignedLoad(IdTy, ReceiverClass, CGF.
getPointerAlign());
2866 llvm::StructType *ObjCSuperTy =
2867 llvm::StructType::get(Receiver->getType(), IdTy);
2872 Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0));
2873 Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1));
2876 llvm::Value *imp = LookupIMPSuper(CGF, ObjCSuper, cmd, MSI);
2877 imp = EnforceType(Builder, imp, MSI.MessengerType);
2879 llvm::Metadata *impMD[] = {
2880 llvm::MDString::get(VMContext, Sel.
getAsString()),
2881 llvm::MDString::get(VMContext,
Class->getSuperClass()->getNameAsString()),
2882 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2883 llvm::Type::getInt1Ty(VMContext), IsClassMessage))};
2884 llvm::MDNode *
node = llvm::MDNode::get(VMContext, impMD);
2886 CGCallee callee(CGCalleeInfo(), imp);
2888 llvm::CallBase *call;
2889 RValue msgRet = CGF.
EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
2890 call->setMetadata(msgSendMDKind, node);
2896CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
2897 ReturnValueSlot Return,
2898 QualType ResultType,
2900 llvm::Value *Receiver,
2901 const CallArgList &CallArgs,
2902 const ObjCInterfaceDecl *
Class,
2903 const ObjCMethodDecl *
Method) {
2904 CGBuilderTy &Builder = CGF.
Builder;
2907 if (CGM.
getLangOpts().getGC() == LangOptions::GCOnly) {
2908 if (Sel == RetainSel || Sel == AutoreleaseSel) {
2912 if (Sel == ReleaseSel) {
2923 cmd = GetSelector(CGF,
Method);
2925 cmd = GetSelector(CGF, Sel);
2926 cmd = EnforceType(Builder, cmd, SelectorTy);
2929 Receiver = EnforceType(Builder, Receiver, IdTy);
2931 llvm::Metadata *impMD[] = {
2932 llvm::MDString::get(VMContext, Sel.
getAsString()),
2933 llvm::MDString::get(VMContext,
Class ?
Class->getNameAsString() :
""),
2934 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2935 llvm::Type::getInt1Ty(VMContext),
Class !=
nullptr))};
2936 llvm::MDNode *
node = llvm::MDNode::get(VMContext, impMD);
2938 CallArgList ActualArgs;
2944 MessageSendInfo MSI = getMessageSendInfo(
Method, ResultType, ActualArgs);
2965 bool hasParamDestroyedInCallee =
false;
2966 bool requiresExplicitZeroResult =
false;
2967 bool requiresNilReceiverCheck = [&] {
2969 if (!canMessageReceiverBeNull(CGF,
Method,
false,
2975 hasParamDestroyedInCallee =
true;
2981 if (CGM.
getTriple().isWasm() && !isDirect) {
2982 requiresExplicitZeroResult =
3005 requiresExplicitZeroResult = !isDirect;
3009 return hasParamDestroyedInCallee || requiresExplicitZeroResult;
3015 bool requiresExplicitAggZeroing =
3019 llvm::BasicBlock *continueBB =
nullptr;
3021 llvm::BasicBlock *nilPathBB =
nullptr;
3023 llvm::BasicBlock *nilCleanupBB =
nullptr;
3026 if (requiresNilReceiverCheck) {
3033 if (requiresExplicitAggZeroing || hasParamDestroyedInCallee) {
3036 nilPathBB = Builder.GetInsertBlock();
3039 llvm::Value *isNil = Builder.CreateICmpEQ(Receiver,
3040 llvm::Constant::getNullValue(Receiver->getType()));
3041 Builder.CreateCondBr(isNil, nilCleanupBB ? nilCleanupBB : continueBB,
3051 imp = GenerateMethod(
Method,
Method->getClassInterface());
3058 imp = LookupIMP(CGF, Receiver, cmd, node, MSI);
3062 StringRef
name =
"objc_msgSend";
3064 name =
"objc_msgSend_fpret";
3066 name =
"objc_msgSend_stret";
3070 bool shouldCheckForInReg =
3074 .isWindowsMSVCEnvironment() &&
3077 name =
"objc_msgSend_stret2";
3088 ActualArgs[0] = CallArg(
RValue::get(Receiver), ASTIdTy);
3090 imp = EnforceType(Builder, imp, MSI.MessengerType);
3092 llvm::CallBase *call;
3093 CGCallee callee(CGCalleeInfo(), imp);
3094 RValue msgRet = CGF.
EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
3096 call->setMetadata(msgSendMDKind, node);
3098 if (requiresNilReceiverCheck) {
3099 llvm::BasicBlock *nonNilPathBB = CGF.
Builder.GetInsertBlock();
3100 CGF.
Builder.CreateBr(continueBB);
3106 if (hasParamDestroyedInCallee) {
3107 destroyCalleeDestroyedArguments(CGF,
Method, CallArgs);
3110 if (requiresExplicitAggZeroing) {
3116 nilPathBB = CGF.
Builder.GetInsertBlock();
3117 CGF.
Builder.CreateBr(continueBB);
3125 llvm::PHINode *phi = Builder.CreatePHI(v->getType(), 2);
3126 phi->addIncoming(v, nonNilPathBB);
3133 std::pair<llvm::Value*,llvm::Value*> v = msgRet.
getComplexVal();
3134 llvm::PHINode *phi = Builder.CreatePHI(v.first->getType(), 2);
3135 phi->addIncoming(v.first, nonNilPathBB);
3136 phi->addIncoming(llvm::Constant::getNullValue(v.first->getType()),
3138 llvm::PHINode *phi2 = Builder.CreatePHI(v.second->getType(), 2);
3139 phi2->addIncoming(v.second, nonNilPathBB);
3140 phi2->addIncoming(llvm::Constant::getNullValue(v.second->getType()),
3150llvm::Constant *CGObjCGNU::
3151GenerateMethodList(StringRef ClassName,
3152 StringRef CategoryName,
3153 ArrayRef<const ObjCMethodDecl*> Methods,
3154 bool isClassMethodList) {
3155 if (Methods.empty())
3158 ConstantInitBuilder Builder(CGM);
3160 auto MethodList = Builder.beginStruct();
3161 MethodList.addNullPointer(CGM.
Int8PtrTy);
3162 MethodList.addInt(Int32Ty, Methods.size());
3165 llvm::StructType *ObjCMethodTy =
3174 const llvm::DataLayout &DL = TheModule.getDataLayout();
3175 MethodList.addInt(SizeTy, DL.getTypeSizeInBits(ObjCMethodTy) /
3191 auto MethodArray = MethodList.beginArray();
3193 for (
const auto *OMD : Methods) {
3194 llvm::Constant *FnPtr =
3195 TheModule.getFunction(getSymbolNameForMethod(OMD));
3196 assert(FnPtr &&
"Can't generate metadata for method that doesn't exist");
3197 auto Method = MethodArray.beginStruct(ObjCMethodTy);
3208 Method.finishAndAddTo(MethodArray);
3210 MethodArray.finishAndAddTo(MethodList);
3213 return MethodList.finishAndCreateGlobal(
".objc_method_list",
3218llvm::Constant *CGObjCGNU::
3219GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
3220 ArrayRef<llvm::Constant *> IvarTypes,
3221 ArrayRef<llvm::Constant *> IvarOffsets,
3222 ArrayRef<llvm::Constant *> IvarAlign,
3223 ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership) {
3224 if (IvarNames.empty())
3227 ConstantInitBuilder Builder(CGM);
3230 auto IvarList = Builder.beginStruct();
3231 IvarList.addInt(IntTy, (
int)IvarNames.size());
3234 llvm::StructType *ObjCIvarTy =
3235 llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy);
3238 auto Ivars = IvarList.beginArray(ObjCIvarTy);
3239 for (
unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
3240 auto Ivar = Ivars.beginStruct(ObjCIvarTy);
3241 Ivar.
add(IvarNames[i]);
3242 Ivar.
add(IvarTypes[i]);
3243 Ivar.
add(IvarOffsets[i]);
3244 Ivar.finishAndAddTo(Ivars);
3246 Ivars.finishAndAddTo(IvarList);
3249 return IvarList.finishAndCreateGlobal(
".objc_ivar_list",
3254llvm::Constant *CGObjCGNU::GenerateClassStructure(
3255 llvm::Constant *MetaClass,
3256 llvm::Constant *SuperClass,
3259 llvm::Constant *Version,
3260 llvm::Constant *InstanceSize,
3261 llvm::Constant *IVars,
3262 llvm::Constant *Methods,
3263 llvm::Constant *Protocols,
3264 llvm::Constant *IvarOffsets,
3265 llvm::Constant *Properties,
3266 llvm::Constant *StrongIvarBitmap,
3267 llvm::Constant *WeakIvarBitmap,
3276 llvm::StructType *ClassTy = llvm::StructType::get(
3293 IvarOffsets->getType(),
3294 Properties->getType(),
3299 ConstantInitBuilder Builder(CGM);
3300 auto Elements = Builder.beginStruct(ClassTy);
3305 Elements.add(MetaClass);
3307 Elements.add(SuperClass);
3309 Elements.add(MakeConstantString(Name,
".class_name"));
3311 Elements.addInt(LongTy, 0);
3313 Elements.addInt(LongTy, info);
3316 const llvm::DataLayout &DL = TheModule.getDataLayout();
3317 Elements.addInt(LongTy, DL.getTypeSizeInBits(ClassTy) /
3320 Elements.add(InstanceSize);
3322 Elements.add(IVars);
3324 Elements.add(Methods);
3327 Elements.add(NULLPtr);
3329 Elements.add(NULLPtr);
3331 Elements.add(NULLPtr);
3333 Elements.add(Protocols);
3335 Elements.add(NULLPtr);
3337 Elements.addInt(LongTy, ClassABIVersion);
3339 Elements.add(IvarOffsets);
3341 Elements.add(Properties);
3343 Elements.add(StrongIvarBitmap);
3345 Elements.add(WeakIvarBitmap);
3350 std::string ClassSym((isMeta ?
"_OBJC_METACLASS_":
"_OBJC_CLASS_") +
3352 llvm::GlobalVariable *ClassRef = TheModule.getNamedGlobal(ClassSym);
3353 llvm::Constant *
Class =
3354 Elements.finishAndCreateGlobal(ClassSym, CGM.
getPointerAlign(),
false,
3355 llvm::GlobalValue::ExternalLinkage);
3357 ClassRef->replaceAllUsesWith(
Class);
3358 ClassRef->removeFromParent();
3359 Class->setName(ClassSym);
3364llvm::Constant *CGObjCGNU::
3365GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods) {
3367 llvm::StructType *ObjCMethodDescTy =
3368 llvm::StructType::get(CGM.
getLLVMContext(), { PtrToInt8Ty, PtrToInt8Ty });
3370 ConstantInitBuilder Builder(CGM);
3371 auto MethodList = Builder.beginStruct();
3372 MethodList.addInt(IntTy, Methods.size());
3373 auto MethodArray = MethodList.beginArray(ObjCMethodDescTy);
3374 for (
auto *M : Methods) {
3375 auto Method = MethodArray.beginStruct(ObjCMethodDescTy);
3376 Method.add(MakeConstantString(M->getSelector().getAsString()));
3378 Method.finishAndAddTo(MethodArray);
3380 MethodArray.finishAndAddTo(MethodList);
3381 return MethodList.finishAndCreateGlobal(
".objc_method_list",
3387CGObjCGNU::GenerateProtocolList(ArrayRef<std::string> Protocols) {
3389 ConstantInitBuilder Builder(CGM);
3390 auto ProtocolList = Builder.beginStruct();
3391 ProtocolList.add(NULLPtr);
3392 ProtocolList.addInt(LongTy, Protocols.size());
3394 auto Elements = ProtocolList.beginArray(PtrToInt8Ty);
3395 for (
const std::string &Protocol : Protocols) {
3396 llvm::Constant *protocol =
nullptr;
3397 llvm::StringMap<llvm::Constant *>::iterator value =
3398 ExistingProtocols.find(Protocol);
3399 if (value == ExistingProtocols.end()) {
3400 protocol = GenerateEmptyProtocol(Protocol);
3402 protocol = value->getValue();
3404 Elements.add(protocol);
3406 Elements.finishAndAddTo(ProtocolList);
3407 return ProtocolList.finishAndCreateGlobal(
".objc_protocol_list",
3411llvm::Value *CGObjCGNU::GenerateProtocolRef(CodeGenFunction &CGF,
3412 const ObjCProtocolDecl *PD) {
3413 return GenerateProtocolRef(PD);
3416llvm::Constant *CGObjCGNU::GenerateProtocolRef(
const ObjCProtocolDecl *PD) {
3419 GenerateProtocol(PD);
3420 assert(protocol &&
"Unknown protocol");
3425CGObjCGNU::GenerateEmptyProtocol(StringRef ProtocolName) {
3426 llvm::Constant *ProtocolList = GenerateProtocolList({});
3427 llvm::Constant *MethodList = GenerateProtocolMethodList({});
3430 ConstantInitBuilder Builder(CGM);
3431 auto Elements = Builder.beginStruct();
3435 Elements.add(llvm::ConstantExpr::getIntToPtr(
3436 llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
3438 Elements.add(MakeConstantString(ProtocolName,
".objc_protocol_name"));
3439 Elements.add(ProtocolList);
3440 Elements.add(MethodList);
3441 Elements.add(MethodList);
3442 Elements.add(MethodList);
3443 Elements.add(MethodList);
3444 Elements.add(NULLPtr);
3445 Elements.add(NULLPtr);
3446 return Elements.finishAndCreateGlobal(SymbolForProtocol(ProtocolName),
3450void CGObjCGNU::GenerateProtocol(
const ObjCProtocolDecl *PD) {
3460 SmallVector<std::string, 16> Protocols;
3462 Protocols.push_back(PI->getNameAsString());
3463 SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
3464 SmallVector<const ObjCMethodDecl*, 16> OptionalInstanceMethods;
3466 if (I->isOptional())
3467 OptionalInstanceMethods.push_back(I);
3469 InstanceMethods.push_back(I);
3471 SmallVector<const ObjCMethodDecl*, 16> ClassMethods;
3472 SmallVector<const ObjCMethodDecl*, 16> OptionalClassMethods;
3474 if (I->isOptional())
3475 OptionalClassMethods.push_back(I);
3477 ClassMethods.push_back(I);
3479 llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
3480 llvm::Constant *InstanceMethodList =
3481 GenerateProtocolMethodList(InstanceMethods);
3482 llvm::Constant *ClassMethodList =
3483 GenerateProtocolMethodList(ClassMethods);
3484 llvm::Constant *OptionalInstanceMethodList =
3485 GenerateProtocolMethodList(OptionalInstanceMethods);
3486 llvm::Constant *OptionalClassMethodList =
3487 GenerateProtocolMethodList(OptionalClassMethods);
3495 llvm::Constant *PropertyList =
3496 GeneratePropertyList(
nullptr, PD,
false,
false);
3497 llvm::Constant *OptionalPropertyList =
3498 GeneratePropertyList(
nullptr, PD,
false,
true);
3504 ConstantInitBuilder Builder(CGM);
3505 auto Elements = Builder.beginStruct();
3507 llvm::ConstantExpr::getIntToPtr(
3508 llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
3509 Elements.add(MakeConstantString(ProtocolName));
3510 Elements.add(ProtocolList);
3511 Elements.add(InstanceMethodList);
3512 Elements.add(ClassMethodList);
3513 Elements.add(OptionalInstanceMethodList);
3514 Elements.add(OptionalClassMethodList);
3515 Elements.add(PropertyList);
3516 Elements.add(OptionalPropertyList);
3517 ExistingProtocols[ProtocolName] =
3518 Elements.finishAndCreateGlobal(
".objc_protocol", CGM.
getPointerAlign());
3520void CGObjCGNU::GenerateProtocolHolderCategory() {
3523 ConstantInitBuilder Builder(CGM);
3524 auto Elements = Builder.beginStruct();
3526 const std::string ClassName =
"__ObjC_Protocol_Holder_Ugly_Hack";
3527 const std::string CategoryName =
"AnotherHack";
3528 Elements.add(MakeConstantString(CategoryName));
3529 Elements.add(MakeConstantString(ClassName));
3531 Elements.add(GenerateMethodList(ClassName, CategoryName, {},
false));
3533 Elements.add(GenerateMethodList(ClassName, CategoryName, {},
true));
3536 ConstantInitBuilder ProtocolListBuilder(CGM);
3537 auto ProtocolList = ProtocolListBuilder.beginStruct();
3538 ProtocolList.add(NULLPtr);
3539 ProtocolList.addInt(LongTy, ExistingProtocols.size());
3540 auto ProtocolElements = ProtocolList.beginArray(PtrTy);
3541 for (
auto iter = ExistingProtocols.begin(), endIter = ExistingProtocols.end();
3542 iter != endIter ; iter++) {
3543 ProtocolElements.add(iter->getValue());
3545 ProtocolElements.finishAndAddTo(ProtocolList);
3546 Elements.add(ProtocolList.finishAndCreateGlobal(
".objc_protocol_list",
3548 Categories.push_back(
3563llvm::Constant *CGObjCGNU::MakeBitField(ArrayRef<bool> bits) {
3564 int bitCount = bits.size();
3566 if (bitCount < ptrBits) {
3568 for (
int i=0 ; i<bitCount ; ++i) {
3569 if (bits[i]) val |= 1ULL<<(i+1);
3571 return llvm::ConstantInt::get(IntPtrTy, val);
3573 SmallVector<llvm::Constant *, 8> values;
3575 while (v < bitCount) {
3577 for (
int i=0 ; (i<32) && (v<bitCount) ; ++i) {
3578 if (bits[v]) word |= 1<<i;
3581 values.push_back(llvm::ConstantInt::get(Int32Ty, word));
3584 ConstantInitBuilder builder(CGM);
3585 auto fields = builder.beginStruct();
3586 fields.addInt(Int32Ty, values.size());
3587 auto array = fields.beginArray();
3588 for (
auto *v : values) array.add(v);
3589 array.finishAndAddTo(fields);
3591 llvm::Constant *GS =
3593 llvm::Constant *ptr = llvm::ConstantExpr::getPtrToInt(GS, IntPtrTy);
3597llvm::Constant *CGObjCGNU::GenerateCategoryProtocolList(
const
3598 ObjCCategoryDecl *OCD) {
3600 const auto RuntimeProtos =
3601 GetRuntimeProtocolList(RefPro.begin(), RefPro.end());
3602 SmallVector<std::string, 16> Protocols;
3603 for (
const auto *PD : RuntimeProtos)
3605 return GenerateProtocolList(Protocols);
3608void CGObjCGNU::GenerateCategory(
const ObjCCategoryImplDecl *OCD) {
3610 std::string ClassName =
Class->getNameAsString();
3616 ConstantInitBuilder Builder(CGM);
3617 auto Elements = Builder.beginStruct();
3618 Elements.add(MakeConstantString(CategoryName));
3619 Elements.add(MakeConstantString(ClassName));
3621 SmallVector<ObjCMethodDecl*, 16> InstanceMethods;
3622 InstanceMethods.insert(InstanceMethods.begin(), OCD->
instmeth_begin(),
3625 GenerateMethodList(ClassName, CategoryName, InstanceMethods,
false));
3629 SmallVector<ObjCMethodDecl*, 16> ClassMethods;
3632 Elements.add(GenerateMethodList(ClassName, CategoryName, ClassMethods,
true));
3635 Elements.add(GenerateCategoryProtocolList(CatDecl));
3637 const ObjCCategoryDecl *Category =
3641 Elements.add(GeneratePropertyList(OCD, Category,
false));
3643 Elements.add(GeneratePropertyList(OCD, Category,
true));
3645 Elements.addNullPointer(PtrTy);
3646 Elements.addNullPointer(PtrTy);
3650 Categories.push_back(Elements.finishAndCreateGlobal(
3651 std::string(
".objc_category_") + ClassName + CategoryName,
3655llvm::Constant *CGObjCGNU::GeneratePropertyList(
const Decl *Container,
3656 const ObjCContainerDecl *OCD,
3657 bool isClassProperty,
3658 bool protocolOptionalProperties) {
3660 SmallVector<const ObjCPropertyDecl *, 16> Properties;
3661 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
3665 std::function<void(
const ObjCProtocolDecl *Proto)> collectProtocolProperties
3666 = [&](
const ObjCProtocolDecl *Proto) {
3667 for (
const auto *P : Proto->protocols())
3668 collectProtocolProperties(P);
3669 for (
const auto *PD : Proto->properties()) {
3670 if (isClassProperty != PD->isClassProperty())
3678 Properties.push_back(PD);
3682 if (
const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
3684 for (
auto *PD : ClassExt->properties()) {
3685 if (isClassProperty != PD->isClassProperty())
3688 Properties.push_back(PD);
3692 if (isClassProperty != PD->isClassProperty())
3696 if (isProtocol && (protocolOptionalProperties != PD->isOptional()))
3703 Properties.push_back(PD);
3706 if (
const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
3708 collectProtocolProperties(P);
3709 else if (
const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD))
3710 for (
const auto *P : CD->protocols())
3711 collectProtocolProperties(P);
3713 auto numProperties = Properties.size();
3715 if (numProperties == 0)
3718 ConstantInitBuilder builder(CGM);
3719 auto propertyList = builder.beginStruct();
3720 auto properties = PushPropertyListHeader(propertyList, numProperties);
3724 for (
auto *property : Properties) {
3725 bool isSynthesized =
false;
3726 bool isDynamic =
false;
3730 isSynthesized = (propertyImpl->getPropertyImplementation() ==
3732 isDynamic = (propertyImpl->getPropertyImplementation() ==
3736 PushProperty(properties, property, Container, isSynthesized, isDynamic);
3738 properties.finishAndAddTo(propertyList);
3740 return propertyList.finishAndCreateGlobal(
".objc_property_list",
3744void CGObjCGNU::RegisterAlias(
const ObjCCompatibleAliasDecl *OAD) {
3746 ObjCInterfaceDecl *ClassDecl =
3752void CGObjCGNU::GenerateClass(
const ObjCImplementationDecl *OID) {
3756 const ObjCInterfaceDecl * SuperClassDecl =
3758 std::string SuperClassName;
3759 if (SuperClassDecl) {
3761 EmitClassRef(SuperClassName);
3765 ObjCInterfaceDecl *ClassDecl =
3771 std::string classSymbolName =
"__objc_class_name_" + ClassName;
3772 if (
auto *symbol = TheModule.getGlobalVariable(classSymbolName)) {
3773 symbol->setInitializer(llvm::ConstantInt::get(LongTy, 0));
3775 new llvm::GlobalVariable(TheModule, LongTy,
false,
3776 llvm::GlobalValue::ExternalLinkage,
3777 llvm::ConstantInt::get(LongTy, 0),
3787 SmallVector<llvm::Constant*, 16> IvarNames;
3788 SmallVector<llvm::Constant*, 16> IvarTypes;
3789 SmallVector<llvm::Constant*, 16> IvarOffsets;
3790 SmallVector<llvm::Constant*, 16> IvarAligns;
3791 SmallVector<Qualifiers::ObjCLifetime, 16> IvarOwnership;
3793 ConstantInitBuilder IvarOffsetBuilder(CGM);
3794 auto IvarOffsetValues = IvarOffsetBuilder.beginArray(PtrToIntTy);
3795 SmallVector<bool, 16> WeakIvars;
3796 SmallVector<bool, 16> StrongIvars;
3798 int superInstanceSize = !SuperClassDecl ? 0 :
3803 instanceSize = 0 - (instanceSize - superInstanceSize);
3809 IvarNames.push_back(MakeConstantString(IVD->getNameAsString()));
3811 std::string TypeStr;
3813 IvarTypes.push_back(MakeConstantString(TypeStr));
3814 IvarAligns.push_back(llvm::ConstantInt::get(IntTy,
3817 uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
3820 Offset =
static_cast<int64_t>(BaseOffset) - superInstanceSize;
3822 llvm::Constant *OffsetValue = llvm::ConstantInt::getSigned(IntTy, Offset);
3824 std::string OffsetName =
"__objc_ivar_offset_value_" + ClassName +
"." +
3825 IVD->getNameAsString();
3827 llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName);
3829 OffsetVar->setInitializer(OffsetValue);
3833 OffsetVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
3835 OffsetVar =
new llvm::GlobalVariable(TheModule, Int32Ty,
3836 false, llvm::GlobalValue::ExternalLinkage,
3837 OffsetValue, OffsetName);
3838 IvarOffsets.push_back(OffsetValue);
3839 IvarOffsetValues.add(OffsetVar);
3841 IvarOwnership.push_back(lt);
3844 StrongIvars.push_back(
true);
3845 WeakIvars.push_back(
false);
3848 StrongIvars.push_back(
false);
3849 WeakIvars.push_back(
true);
3852 StrongIvars.push_back(
false);
3853 WeakIvars.push_back(
false);
3856 llvm::Constant *StrongIvarBitmap = MakeBitField(StrongIvars);
3857 llvm::Constant *WeakIvarBitmap = MakeBitField(WeakIvars);
3858 llvm::GlobalVariable *IvarOffsetArray =
3859 IvarOffsetValues.finishAndCreateGlobal(
".ivar.offsets",
3863 SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
3864 InstanceMethods.insert(InstanceMethods.begin(), OID->
instmeth_begin(),
3867 SmallVector<const ObjCMethodDecl*, 16> ClassMethods;
3871 llvm::Constant *Properties = GeneratePropertyList(OID, ClassDecl);
3874 auto RefProtocols = ClassDecl->
protocols();
3875 auto RuntimeProtocols =
3876 GetRuntimeProtocolList(RefProtocols.begin(), RefProtocols.end());
3877 SmallVector<std::string, 16> Protocols;
3878 for (
const auto *I : RuntimeProtocols)
3879 Protocols.push_back(I->getNameAsString());
3882 llvm::Constant *SuperClass;
3883 if (!SuperClassName.empty()) {
3884 SuperClass = MakeConstantString(SuperClassName,
".super_class_name");
3886 SuperClass = llvm::ConstantPointerNull::get(PtrToInt8Ty);
3889 llvm::Constant *MethodList = GenerateMethodList(ClassName,
"",
3890 InstanceMethods,
false);
3891 llvm::Constant *ClassMethodList = GenerateMethodList(ClassName,
"",
3892 ClassMethods,
true);
3893 llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
3894 IvarOffsets, IvarAligns, IvarOwnership);
3905 llvm::Type *IndexTy = Int32Ty;
3906 llvm::Constant *offsetPointerIndexes[] = {Zeros[0],
3907 llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 2 : 1),
nullptr,
3908 llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 3 : 2) };
3910 unsigned ivarIndex = 0;
3913 const std::string Name = GetIVarOffsetVariableName(ClassDecl, IVD);
3914 offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, ivarIndex);
3916 llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr(
3918 offsetPointerIndexes);
3920 llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name);
3922 offset->setInitializer(offsetValue);
3926 offset->setLinkage(llvm::GlobalValue::ExternalLinkage);
3929 new llvm::GlobalVariable(TheModule, offsetValue->getType(),
3930 false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name);
3933 llvm::Constant *ZeroPtr = llvm::ConstantInt::get(IntPtrTy, 0);
3936 llvm::Constant *MetaClassStruct = GenerateClassStructure(
3937 NULLPtr, NULLPtr, 0x12L, ClassName.c_str(),
nullptr, Zeros[0],
3938 NULLPtr, ClassMethodList, NULLPtr, NULLPtr,
3939 GeneratePropertyList(OID, ClassDecl,
true), ZeroPtr, ZeroPtr,
true);
3944 llvm::Constant *ClassStruct = GenerateClassStructure(
3945 MetaClassStruct, SuperClass, 0x11L, ClassName.c_str(),
nullptr,
3946 llvm::ConstantInt::getSigned(LongTy, instanceSize), IvarList, MethodList,
3947 GenerateProtocolList(Protocols), IvarOffsetArray, Properties,
3948 StrongIvarBitmap, WeakIvarBitmap);
3953 if (ClassPtrAlias) {
3954 ClassPtrAlias->replaceAllUsesWith(ClassStruct);
3955 ClassPtrAlias->eraseFromParent();
3956 ClassPtrAlias =
nullptr;
3958 if (MetaClassPtrAlias) {
3959 MetaClassPtrAlias->replaceAllUsesWith(MetaClassStruct);
3960 MetaClassPtrAlias->eraseFromParent();
3961 MetaClassPtrAlias =
nullptr;
3965 Classes.push_back(ClassStruct);
3968llvm::Function *CGObjCGNU::ModuleInitFunction() {
3970 if (Classes.empty() && Categories.empty() && ConstantStrings.empty() &&
3971 ExistingProtocols.empty() && SelectorTable.empty())
3975 GenerateProtocolHolderCategory();
3977 llvm::StructType *selStructTy = dyn_cast<llvm::StructType>(SelectorElemTy);
3980 { PtrToInt8Ty, PtrToInt8Ty });
3984 llvm::Constant *statics = NULLPtr;
3985 if (!ConstantStrings.empty()) {
3986 llvm::GlobalVariable *fileStatics = [&] {
3987 ConstantInitBuilder builder(CGM);
3988 auto staticsStruct = builder.beginStruct();
3991 if (stringClass.empty()) stringClass =
"NXConstantString";
3992 staticsStruct.add(MakeConstantString(stringClass,
3993 ".objc_static_class_name"));
3995 auto array = staticsStruct.beginArray();
3996 array.addAll(ConstantStrings);
3998 array.finishAndAddTo(staticsStruct);
4000 return staticsStruct.finishAndCreateGlobal(
".objc_statics",
4004 ConstantInitBuilder builder(CGM);
4005 auto allStaticsArray = builder.beginArray(fileStatics->getType());
4006 allStaticsArray.add(fileStatics);
4007 allStaticsArray.addNullPointer(fileStatics->getType());
4009 statics = allStaticsArray.finishAndCreateGlobal(
".objc_statics_ptr",
4015 SmallVector<llvm::GlobalAlias*, 16> selectorAliases;
4016 unsigned selectorCount;
4019 llvm::GlobalVariable *selectorList = [&] {
4020 ConstantInitBuilder builder(CGM);
4021 auto selectors = builder.beginArray(selStructTy);
4022 auto &table = SelectorTable;
4023 std::vector<Selector> allSelectors;
4024 for (
auto &entry : table)
4025 allSelectors.push_back(entry.first);
4026 llvm::sort(allSelectors);
4028 for (
auto &untypedSel : allSelectors) {
4029 std::string selNameStr = untypedSel.getAsString();
4030 llvm::Constant *selName = ExportUniqueString(selNameStr,
".objc_sel_name");
4032 for (TypedSelector &sel : table[untypedSel]) {
4033 llvm::Constant *selectorTypeEncoding = NULLPtr;
4034 if (!sel.first.empty())
4035 selectorTypeEncoding =
4036 MakeConstantString(sel.first,
".objc_sel_types");
4038 auto selStruct = selectors.beginStruct(selStructTy);
4039 selStruct.add(selName);
4040 selStruct.add(selectorTypeEncoding);
4041 selStruct.finishAndAddTo(selectors);
4044 selectorAliases.push_back(sel.second);
4049 selectorCount = selectors.size();
4055 auto selStruct = selectors.beginStruct(selStructTy);
4056 selStruct.add(NULLPtr);
4057 selStruct.add(NULLPtr);
4058 selStruct.finishAndAddTo(selectors);
4060 return selectors.finishAndCreateGlobal(
".objc_selector_list",
4065 for (
unsigned i = 0; i < selectorCount; ++i) {
4066 llvm::Constant *idxs[] = {
4068 llvm::ConstantInt::get(Int32Ty, i)
4071 llvm::Constant *selPtr = llvm::ConstantExpr::getGetElementPtr(
4072 selectorList->getValueType(), selectorList, idxs);
4073 selectorAliases[i]->replaceAllUsesWith(selPtr);
4074 selectorAliases[i]->eraseFromParent();
4077 llvm::GlobalVariable *symtab = [&] {
4078 ConstantInitBuilder builder(CGM);
4079 auto symtab = builder.beginStruct();
4082 symtab.addInt(LongTy, selectorCount);
4084 symtab.add(selectorList);
4087 symtab.addInt(CGM.
Int16Ty, Classes.size());
4089 symtab.addInt(CGM.
Int16Ty, Categories.size());
4092 auto classList = symtab.beginArray(PtrToInt8Ty);
4093 classList.addAll(Classes);
4094 classList.addAll(Categories);
4096 classList.add(statics);
4097 classList.add(NULLPtr);
4098 classList.finishAndAddTo(symtab);
4106 llvm::Constant *module = [&] {
4107 llvm::Type *moduleEltTys[] = {
4108 LongTy, LongTy, PtrToInt8Ty, symtab->getType(), IntTy
4110 llvm::StructType *moduleTy = llvm::StructType::get(
4112 ArrayRef(moduleEltTys).drop_back(
unsigned(RuntimeVersion < 10)));
4114 ConstantInitBuilder builder(CGM);
4115 auto module = builder.beginStruct(moduleTy);
4117 module.addInt(LongTy, RuntimeVersion);
4119 module.addInt(LongTy, CGM.getDataLayout().getTypeStoreSize(moduleTy));
4126 module.add(MakeConstantString(path, ".objc_source_file_name"));
4129 if (RuntimeVersion >= 10) {
4131 case LangOptions::GCOnly:
4132 module.addInt(IntTy, 2);
4134 case LangOptions::NonGC:
4136 module.addInt(IntTy, 1);
4138 module.addInt(IntTy, 0);
4140 case LangOptions::HybridGC:
4141 module.addInt(IntTy, 1);
4146 return module.finishAndCreateGlobal("", CGM.getPointerAlign());
4151 llvm::Function * LoadFunction = llvm::Function::Create(
4152 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
false),
4153 llvm::GlobalValue::InternalLinkage,
".objc_load_function",
4155 llvm::BasicBlock *EntryBB =
4156 llvm::BasicBlock::Create(VMContext,
"entry", LoadFunction);
4157 CGBuilderTy Builder(CGM, VMContext);
4158 Builder.SetInsertPoint(EntryBB);
4160 llvm::FunctionType *FT =
4161 llvm::FunctionType::get(Builder.getVoidTy(), module->getType(),
true);
4162 llvm::FunctionCallee Register =
4164 Builder.CreateCall(Register, module);
4166 if (!ClassAliases.empty()) {
4167 llvm::Type *ArgTypes[2] = {PtrTy, PtrToInt8Ty};
4168 llvm::FunctionType *RegisterAliasTy =
4169 llvm::FunctionType::get(Builder.getVoidTy(), ArgTypes,
false);
4170 llvm::Function *RegisterAlias = llvm::Function::Create(
4172 llvm::GlobalValue::ExternalWeakLinkage,
"class_registerAlias_np",
4174 llvm::BasicBlock *AliasBB =
4175 llvm::BasicBlock::Create(VMContext,
"alias", LoadFunction);
4176 llvm::BasicBlock *NoAliasBB =
4177 llvm::BasicBlock::Create(VMContext,
"no_alias", LoadFunction);
4180 llvm::Value *HasRegisterAlias = Builder.CreateICmpNE(RegisterAlias,
4181 llvm::Constant::getNullValue(RegisterAlias->getType()));
4182 Builder.CreateCondBr(HasRegisterAlias, AliasBB, NoAliasBB);
4185 Builder.SetInsertPoint(AliasBB);
4187 for (std::vector<ClassAliasPair>::iterator iter = ClassAliases.begin();
4188 iter != ClassAliases.end(); ++iter) {
4189 llvm::Constant *TheClass =
4190 TheModule.getGlobalVariable(
"_OBJC_CLASS_" + iter->first,
true);
4192 Builder.CreateCall(RegisterAlias,
4193 {TheClass, MakeConstantString(iter->second)});
4197 Builder.CreateBr(NoAliasBB);
4200 Builder.SetInsertPoint(NoAliasBB);
4202 Builder.CreateRetVoid();
4204 return LoadFunction;
4207llvm::Function *CGObjCGNU::GenerateMethod(
const ObjCMethodDecl *OMD,
4208 const ObjCContainerDecl *CD) {
4209 CodeGenTypes &Types = CGM.
getTypes();
4210 llvm::FunctionType *MethodTy =
4214 std::string FunctionName =
4215 getSymbolNameForMethod(OMD, !isDirect);
4218 return llvm::Function::Create(MethodTy,
4219 llvm::GlobalVariable::InternalLinkage,
4220 FunctionName, &TheModule);
4223 auto I = DirectMethodDefinitions.find(COMD);
4224 llvm::Function *OldFn =
nullptr, *
Fn =
nullptr;
4226 if (I == DirectMethodDefinitions.end()) {
4228 llvm::Function::Create(MethodTy, llvm::GlobalVariable::ExternalLinkage,
4229 FunctionName, &TheModule);
4230 DirectMethodDefinitions.insert(std::make_pair(COMD, F));
4247 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
"",
4249 Fn->takeName(OldFn);
4250 OldFn->replaceAllUsesWith(Fn);
4251 OldFn->eraseFromParent();
4258void CGObjCGNU::GenerateDirectMethodsPreconditionCheck(
4259 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
4260 const ObjCContainerDecl *CD) {
4262 "Direct method precondition checks not supported in GNU runtime yet");
4265void CGObjCGNU::GenerateDirectMethodPrologue(CodeGenFunction &CGF,
4267 const ObjCMethodDecl *OMD,
4268 const ObjCContainerDecl *CD) {
4270 "Direct method precondition checks not supported in GNU runtime yet");
4273llvm::FunctionCallee CGObjCGNU::GetPropertyGetFunction() {
4274 return GetPropertyFn;
4277llvm::FunctionCallee CGObjCGNU::GetPropertySetFunction() {
4278 return SetPropertyFn;
4281llvm::FunctionCallee CGObjCGNU::GetOptimizedPropertySetFunction(
bool atomic,
4286llvm::FunctionCallee CGObjCGNU::GetGetStructFunction() {
4287 return GetStructPropertyFn;
4290llvm::FunctionCallee CGObjCGNU::GetSetStructFunction() {
4291 return SetStructPropertyFn;
4294llvm::FunctionCallee CGObjCGNU::GetCppAtomicObjectGetFunction() {
4298llvm::FunctionCallee CGObjCGNU::GetCppAtomicObjectSetFunction() {
4302llvm::FunctionCallee CGObjCGNU::EnumerationMutationFunction() {
4303 return EnumerationMutationFn;
4306void CGObjCGNU::EmitSynchronizedStmt(CodeGenFunction &CGF,
4307 const ObjCAtSynchronizedStmt &S) {
4308 EmitAtSynchronizedStmt(CGF, S, SyncEnterFn, SyncExitFn);
4312void CGObjCGNU::EmitTryStmt(CodeGenFunction &CGF,
4313 const ObjCAtTryStmt &S) {
4325 EmitTryCatchStmt(CGF, S, EnterCatchFn, ExitCatchFn, ExceptionReThrowFn);
4328void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
4329 const ObjCAtThrowStmt &S,
4330 bool ClearInsertionPoint) {
4331 llvm::Value *ExceptionAsObject;
4332 bool isRethrow =
false;
4336 ExceptionAsObject = Exception;
4339 "Unexpected rethrow outside @catch block.");
4343 if (isRethrow && (usesSEHExceptions || usesCxxExceptions)) {
4353 ExceptionAsObject = CGF.
Builder.CreateBitCast(ExceptionAsObject, IdTy);
4354 llvm::CallBase *Throw =
4356 Throw->setDoesNotReturn();
4357 CGF.
Builder.CreateUnreachable();
4359 if (ClearInsertionPoint)
4360 CGF.
Builder.ClearInsertionPoint();
4363llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGenFunction &CGF,
4364 Address AddrWeakObj) {
4366 return B.CreateCall(
4367 WeakReadFn, EnforceType(B, AddrWeakObj.
emitRawPointer(CGF), PtrToIdTy));
4370void CGObjCGNU::EmitObjCWeakAssign(CodeGenFunction &CGF,
4371 llvm::Value *src, Address dst) {
4373 src = EnforceType(B, src, IdTy);
4374 llvm::Value *dstVal = EnforceType(B, dst.
emitRawPointer(CGF), PtrToIdTy);
4375 B.CreateCall(WeakAssignFn, {src, dstVal});
4378void CGObjCGNU::EmitObjCGlobalAssign(CodeGenFunction &CGF,
4379 llvm::Value *src, Address dst,
4382 src = EnforceType(B, src, IdTy);
4383 llvm::Value *dstVal = EnforceType(B, dst.
emitRawPointer(CGF), PtrToIdTy);
4385 assert(!threadlocal &&
"EmitObjCGlobalAssign - Threal Local API NYI");
4386 B.CreateCall(GlobalAssignFn, {src, dstVal});
4389void CGObjCGNU::EmitObjCIvarAssign(CodeGenFunction &CGF,
4390 llvm::Value *src, Address dst,
4391 llvm::Value *ivarOffset) {
4393 src = EnforceType(B, src, IdTy);
4394 llvm::Value *dstVal = EnforceType(B, dst.
emitRawPointer(CGF), IdTy);
4395 B.CreateCall(IvarAssignFn, {src, dstVal, ivarOffset});
4398void CGObjCGNU::EmitObjCStrongCastAssign(CodeGenFunction &CGF,
4399 llvm::Value *src, Address dst) {
4401 src = EnforceType(B, src, IdTy);
4402 llvm::Value *dstVal = EnforceType(B, dst.
emitRawPointer(CGF), PtrToIdTy);
4403 B.CreateCall(StrongCastAssignFn, {src, dstVal});
4406void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF,
4409 llvm::Value *Size) {
4411 llvm::Value *DestPtrVal = EnforceType(B, DestPtr.
emitRawPointer(CGF), PtrTy);
4412 llvm::Value *SrcPtrVal = EnforceType(B, SrcPtr.
emitRawPointer(CGF), PtrTy);
4414 B.CreateCall(MemMoveFn, {DestPtrVal, SrcPtrVal,
Size});
4417llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable(
4418 const ObjCInterfaceDecl *ID,
4419 const ObjCIvarDecl *Ivar) {
4420 const std::string Name = GetIVarOffsetVariableName(ID, Ivar);
4424 llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
4425 if (!IvarOffsetPointer)
4426 IvarOffsetPointer =
new llvm::GlobalVariable(
4427 TheModule, llvm::PointerType::getUnqual(VMContext),
false,
4428 llvm::GlobalValue::ExternalLinkage,
nullptr, Name);
4429 return IvarOffsetPointer;
4432LValue CGObjCGNU::EmitObjCValueForIvar(CodeGenFunction &CGF,
4434 llvm::Value *BaseValue,
4435 const ObjCIvarDecl *Ivar,
4436 unsigned CVRQualifiers) {
4437 const ObjCInterfaceDecl *
ID =
4438 ObjectTy->
castAs<ObjCObjectType>()->getInterface();
4439 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4440 EmitIvarOffset(CGF, ID, Ivar));
4459llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF,
4461 const ObjCIvarDecl *Ivar) {
4468 if (RuntimeVersion < 10 ||
4470 return CGF.
Builder.CreateZExtOrBitCast(
4474 llvm::PointerType::getUnqual(VMContext),
4475 ObjCIvarOffsetVariable(
Interface, Ivar),
4479 std::string
name =
"__objc_ivar_offset_value_" +
4482 llvm::Value *Offset = TheModule.getGlobalVariable(name);
4484 auto GV =
new llvm::GlobalVariable(TheModule, IntTy,
4485 false, llvm::GlobalValue::LinkOnceAnyLinkage,
4486 llvm::Constant::getNullValue(IntTy), name);
4491 if (Offset->getType() != PtrDiffTy)
4492 Offset = CGF.
Builder.CreateZExtOrBitCast(Offset, PtrDiffTy);
4496 return llvm::ConstantInt::get(PtrDiffTy, Offset,
true);
4502 switch (Runtime.getKind()) {
4504 if (Runtime.getVersion() >= VersionTuple(2, 0))
4505 return new CGObjCGNUstep2(CGM);
4506 return new CGObjCGNUstep(CGM);
4509 return new CGObjCGCC(CGM);
4512 return new CGObjCObjFW(CGM);
4518 llvm_unreachable(
"these runtimes are not GNU runtimes");
4520 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])
Result
Implement __builtin_bit_cast and related operations.
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.
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...
void EmitNoreturnRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args)
Emits a call or invoke to the given noreturn runtime function.
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.
OptionalFileEntryRef getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
FileID getMainFileID() const
Returns the FileID of the main source file.
bool containsNonAscii() const
Scans the string contents for any non-ascii characters.
unsigned getLength() const
uint32_t getCodeUnit(size_t I) const
Return the code unit at the given position.
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.
Top level wrappers for InstallAPI frontend operations.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ 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.
const FunctionProtoType * T
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
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 int32_t
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
CharUnits getIntAlign() const
llvm::IntegerType * Int16Ty
llvm::PointerType * Int8PtrTy
CharUnits getPointerAlign() const