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;
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 =
201 return Array.getPointer();
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 *)
override;
569 GenerateMessageSend(CodeGenFunction &CGF, ReturnValueSlot Return,
570 QualType ResultType, Selector Sel,
571 llvm::Value *Receiver,
const CallArgList &CallArgs,
572 const ObjCInterfaceDecl *
Class,
573 const ObjCMethodDecl *
Method)
override;
575 GenerateMessageSendSuper(CodeGenFunction &CGF, ReturnValueSlot Return,
576 QualType ResultType, Selector Sel,
577 const ObjCInterfaceDecl *
Class,
578 bool isCategoryImpl, llvm::Value *Receiver,
579 bool IsClassMessage,
const CallArgList &CallArgs,
580 const ObjCMethodDecl *
Method)
override;
581 llvm::Value *GetClass(CodeGenFunction &CGF,
582 const ObjCInterfaceDecl *OID)
override;
583 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel)
override;
584 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel)
override;
585 llvm::Value *GetSelector(CodeGenFunction &CGF,
586 const ObjCMethodDecl *
Method)
override;
587 virtual llvm::Constant *GetConstantSelector(Selector Sel,
588 const std::string &TypeEncoding) {
589 llvm_unreachable(
"Runtime unable to generate constant selector");
591 llvm::Constant *GetConstantSelector(
const ObjCMethodDecl *M) {
595 llvm::Constant *GetEHType(QualType
T)
override;
597 llvm::Function *GenerateMethod(
const ObjCMethodDecl *OMD,
598 const ObjCContainerDecl *CD)
override;
601 llvm::DenseMap<const ObjCMethodDecl *, llvm::Function *>
602 DirectMethodDefinitions;
603 void GenerateDirectMethodsPreconditionCheck(
604 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
605 const ObjCContainerDecl *CD)
override;
606 void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
607 const ObjCMethodDecl *OMD,
608 const ObjCContainerDecl *CD)
override;
609 void GenerateCategory(
const ObjCCategoryImplDecl *CMD)
override;
610 void GenerateClass(
const ObjCImplementationDecl *ClassDecl)
override;
611 void RegisterAlias(
const ObjCCompatibleAliasDecl *OAD)
override;
612 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
613 const ObjCProtocolDecl *PD)
override;
614 void GenerateProtocol(
const ObjCProtocolDecl *PD)
override;
616 virtual llvm::Constant *GenerateProtocolRef(
const ObjCProtocolDecl *PD);
618 llvm::Constant *GetOrEmitProtocol(
const ObjCProtocolDecl *PD)
override {
619 return GenerateProtocolRef(PD);
622 llvm::Function *ModuleInitFunction()
override;
623 llvm::FunctionCallee GetPropertyGetFunction()
override;
624 llvm::FunctionCallee GetPropertySetFunction()
override;
625 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
627 llvm::FunctionCallee GetSetStructFunction()
override;
628 llvm::FunctionCallee GetGetStructFunction()
override;
629 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override;
630 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override;
631 llvm::FunctionCallee EnumerationMutationFunction()
override;
633 void EmitTryStmt(CodeGenFunction &CGF,
634 const ObjCAtTryStmt &S)
override;
635 void EmitSynchronizedStmt(CodeGenFunction &CGF,
636 const ObjCAtSynchronizedStmt &S)
override;
637 void EmitThrowStmt(CodeGenFunction &CGF,
638 const ObjCAtThrowStmt &S,
639 bool ClearInsertionPoint=
true)
override;
640 llvm::Value * EmitObjCWeakRead(CodeGenFunction &CGF,
641 Address AddrWeakObj)
override;
642 void EmitObjCWeakAssign(CodeGenFunction &CGF,
643 llvm::Value *src, Address dst)
override;
644 void EmitObjCGlobalAssign(CodeGenFunction &CGF,
645 llvm::Value *src, Address dest,
646 bool threadlocal=
false)
override;
647 void EmitObjCIvarAssign(CodeGenFunction &CGF, llvm::Value *src,
648 Address dest, llvm::Value *ivarOffset)
override;
649 void EmitObjCStrongCastAssign(CodeGenFunction &CGF,
650 llvm::Value *src, Address dest)
override;
651 void EmitGCMemmoveCollectable(CodeGenFunction &CGF, Address DestPtr,
653 llvm::Value *Size)
override;
654 LValue EmitObjCValueForIvar(CodeGenFunction &CGF, QualType ObjectTy,
655 llvm::Value *BaseValue,
const ObjCIvarDecl *Ivar,
656 unsigned CVRQualifiers)
override;
657 llvm::Value *EmitIvarOffset(CodeGenFunction &CGF,
659 const ObjCIvarDecl *Ivar)
override;
660 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF)
override;
661 llvm::Constant *BuildGCBlockLayout(CodeGenModule &CGM,
662 const CGBlockInfo &blockInfo)
override {
665 llvm::Constant *BuildRCBlockLayout(CodeGenModule &CGM,
666 const CGBlockInfo &blockInfo)
override {
670 llvm::Constant *BuildByrefLayout(CodeGenModule &CGM, QualType
T)
override {
683class CGObjCGCC :
public CGObjCGNU {
686 LazyRuntimeFunction MsgLookupFn;
690 LazyRuntimeFunction MsgLookupSuperFn;
693 llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver,
694 llvm::Value *cmd, llvm::MDNode *node,
695 MessageSendInfo &MSI)
override {
696 CGBuilderTy &Builder = CGF.
Builder;
697 llvm::Value *args[] = {
698 EnforceType(Builder, Receiver, IdTy),
699 EnforceType(Builder, cmd, SelectorTy) };
701 imp->setMetadata(msgSendMDKind, node);
705 llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
706 llvm::Value *cmd, MessageSendInfo &MSI)
override {
707 CGBuilderTy &Builder = CGF.
Builder;
708 llvm::Value *lookupArgs[] = {
709 EnforceType(Builder, ObjCSuper.
emitRawPointer(CGF), PtrToObjCSuperTy),
715 CGObjCGCC(CodeGenModule &Mod) : CGObjCGNU(Mod, 8, 2) {
717 MsgLookupFn.init(&CGM,
"objc_msg_lookup", IMPTy, IdTy, SelectorTy);
719 MsgLookupSuperFn.init(&CGM,
"objc_msg_lookup_super", IMPTy,
720 PtrToObjCSuperTy, SelectorTy);
725class CGObjCGNUstep :
public CGObjCGNU {
728 LazyRuntimeFunction SlotLookupFn;
733 LazyRuntimeFunction SlotLookupSuperFn;
735 LazyRuntimeFunction SetPropertyAtomic;
737 LazyRuntimeFunction SetPropertyAtomicCopy;
739 LazyRuntimeFunction SetPropertyNonAtomic;
741 LazyRuntimeFunction SetPropertyNonAtomicCopy;
744 LazyRuntimeFunction CxxAtomicObjectGetFn;
747 LazyRuntimeFunction CxxAtomicObjectSetFn;
752 llvm::Type *SlotStructTy;
755 llvm::Constant *GetEHType(QualType
T)
override;
758 llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver,
759 llvm::Value *cmd, llvm::MDNode *node,
760 MessageSendInfo &MSI)
override {
761 CGBuilderTy &Builder = CGF.
Builder;
762 llvm::FunctionCallee LookupFn = SlotLookupFn;
765 RawAddress ReceiverPtr =
767 Builder.CreateStore(Receiver, ReceiverPtr);
774 self = llvm::ConstantPointerNull::get(IdTy);
778 if (
auto *LookupFn2 = dyn_cast<llvm::Function>(LookupFn.getCallee()))
779 LookupFn2->addParamAttr(
781 llvm::CaptureInfo::none()));
783 llvm::Value *args[] = {
784 EnforceType(Builder, ReceiverPtr.
getPointer(), PtrToIdTy),
785 EnforceType(Builder, cmd, SelectorTy),
786 EnforceType(Builder, self, IdTy)};
788 slot->setOnlyReadsMemory();
789 slot->setMetadata(msgSendMDKind, node);
792 llvm::Value *imp = Builder.CreateAlignedLoad(
793 IMPTy, Builder.CreateStructGEP(SlotStructTy, slot, 4),
798 Receiver = Builder.CreateLoad(ReceiverPtr,
true);
802 llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
804 MessageSendInfo &MSI)
override {
805 CGBuilderTy &Builder = CGF.
Builder;
808 llvm::CallInst *slot =
810 slot->setOnlyReadsMemory();
812 return Builder.CreateAlignedLoad(
813 IMPTy, Builder.CreateStructGEP(SlotStructTy, slot, 4),
818 CGObjCGNUstep(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 9, 3, 1) {}
819 CGObjCGNUstep(CodeGenModule &Mod,
unsigned ABI,
unsigned ProtocolABI,
821 CGObjCGNU(Mod, ABI, ProtocolABI, ClassABI) {
822 const ObjCRuntime &R = CGM.
getLangOpts().ObjCRuntime;
824 SlotStructTy = llvm::StructType::get(PtrTy, PtrTy, PtrTy, IntTy, IMPTy);
827 SlotLookupFn.init(&CGM,
"objc_msg_lookup_sender", SlotTy, PtrToIdTy,
830 SlotLookupSuperFn.init(&CGM,
"objc_slot_lookup_super", SlotTy,
831 PtrToObjCSuperTy, SelectorTy);
833 llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
834 if (usesCxxExceptions) {
836 EnterCatchFn.init(&CGM,
"__cxa_begin_catch", PtrTy, PtrTy);
838 ExitCatchFn.init(&CGM,
"__cxa_end_catch", VoidTy);
840 ExceptionReThrowFn.init(&CGM,
"__cxa_rethrow", PtrTy);
841 }
else if (usesSEHExceptions) {
843 ExceptionReThrowFn.init(&CGM,
"objc_exception_rethrow", VoidTy);
846 EnterCatchFn.init(&CGM,
"__cxa_begin_catch", PtrTy, PtrTy);
848 ExitCatchFn.init(&CGM,
"__cxa_end_catch", VoidTy);
850 ExceptionReThrowFn.init(&CGM,
"_Unwind_Resume_or_Rethrow", VoidTy,
852 }
else if (R.
getVersion() >= VersionTuple(1, 7)) {
854 EnterCatchFn.init(&CGM,
"objc_begin_catch", IdTy, PtrTy);
856 ExitCatchFn.init(&CGM,
"objc_end_catch", VoidTy);
858 ExceptionReThrowFn.init(&CGM,
"objc_exception_rethrow", VoidTy, PtrTy);
860 SetPropertyAtomic.init(&CGM,
"objc_setProperty_atomic", VoidTy, IdTy,
861 SelectorTy, IdTy, PtrDiffTy);
862 SetPropertyAtomicCopy.init(&CGM,
"objc_setProperty_atomic_copy", VoidTy,
863 IdTy, SelectorTy, IdTy, PtrDiffTy);
864 SetPropertyNonAtomic.init(&CGM,
"objc_setProperty_nonatomic", VoidTy,
865 IdTy, SelectorTy, IdTy, PtrDiffTy);
866 SetPropertyNonAtomicCopy.init(&CGM,
"objc_setProperty_nonatomic_copy",
867 VoidTy, IdTy, SelectorTy, IdTy, PtrDiffTy);
870 CxxAtomicObjectSetFn.init(&CGM,
"objc_setCppObjectAtomic", VoidTy, PtrTy,
874 CxxAtomicObjectGetFn.init(&CGM,
"objc_getCppObjectAtomic", VoidTy, PtrTy,
878 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override {
883 return CxxAtomicObjectGetFn;
886 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override {
891 return CxxAtomicObjectSetFn;
894 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
895 bool copy)
override {
899 assert ((CGM.
getLangOpts().getGC() == LangOptions::NonGC));
906 if (copy)
return SetPropertyAtomicCopy;
907 return SetPropertyAtomic;
910 return copy ? SetPropertyNonAtomicCopy : SetPropertyNonAtomic;
917class CGObjCGNUstep2 :
public CGObjCGNUstep {
922 ClassReferenceSection,
925 ProtocolReferenceSection,
927 ConstantStringSection
932 ClassFlagMeta = (1 << 0),
935 ClassFlagInitialized = (1 << 8),
937 static const char *
const SectionsBaseNames[8];
938 static const char *
const PECOFFSectionsBaseNames[8];
939 template<SectionKind K>
940 std::string sectionName() {
941 if (CGM.
getTriple().isOSBinFormatCOFF()) {
942 std::string
name(PECOFFSectionsBaseNames[K]);
946 return SectionsBaseNames[K];
951 LazyRuntimeFunction MsgLookupSuperFn;
953 LazyRuntimeFunction SentInitializeFn;
957 bool EmittedProtocol =
false;
962 bool EmittedProtocolRef =
false;
966 bool EmittedClass =
false;
970 typedef std::pair<std::string, std::pair<llvm::GlobalVariable*, int>>
972 std::vector<EarlyInitPair> EarlyInitList;
974 std::string SymbolForClassRef(StringRef Name,
bool isWeak) {
976 return (ManglePublicSymbol(
"OBJC_WEAK_REF_CLASS_") + Name).str();
978 return (ManglePublicSymbol(
"OBJC_REF_CLASS_") + Name).str();
981 std::string SymbolForClass(StringRef Name) {
982 return (ManglePublicSymbol(
"OBJC_CLASS_") + Name).str();
984 void CallRuntimeFunction(CGBuilderTy &B, StringRef FunctionName,
985 ArrayRef<llvm::Value*> Args) {
986 SmallVector<llvm::Type *,8> Types;
987 for (
auto *Arg : Args)
988 Types.push_back(Arg->getType());
989 llvm::FunctionType *FT = llvm::FunctionType::get(B.getVoidTy(), Types,
992 B.CreateCall(Fn, Args);
995 ConstantAddress GenerateConstantString(
const StringLiteral *SL)
override {
1001 llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
1002 if (old != ObjCStrings.end())
1003 return ConstantAddress(old->getValue(), IdElemTy, Align);
1010 (LiteralLength < 9) && !isNonASCII) {
1016 for (
unsigned i=0 ; i<LiteralLength ; i++)
1017 str |= ((uint64_t)SL->
getCodeUnit(i)) << ((64 - 4 - 3) - (i*7));
1019 str |= LiteralLength << 3;
1022 auto *ObjCStr = llvm::ConstantExpr::getIntToPtr(
1023 llvm::ConstantInt::get(Int64Ty, str), IdTy);
1024 ObjCStrings[Str] = ObjCStr;
1025 return ConstantAddress(ObjCStr, IdElemTy, Align);
1030 if (StringClass.empty()) StringClass =
"NSConstantString";
1032 std::string Sym = SymbolForClass(StringClass);
1034 llvm::Constant *
isa = TheModule.getNamedGlobal(Sym);
1037 isa =
new llvm::GlobalVariable(TheModule, IdTy,
false,
1038 llvm::GlobalValue::ExternalLinkage,
nullptr, Sym);
1039 if (CGM.
getTriple().isOSBinFormatCOFF()) {
1054 ConstantInitBuilder Builder(CGM);
1055 auto Fields = Builder.beginStruct();
1056 if (!CGM.
getTriple().isOSBinFormatCOFF()) {
1066 unsigned NumU8CodeUnits = Str.size();
1070 SmallVector<llvm::UTF16, 128> ToBuf(NumU8CodeUnits + 1);
1071 const llvm::UTF8 *FromPtr = (
const llvm::UTF8 *)Str.data();
1072 llvm::UTF16 *ToPtr = &ToBuf[0];
1073 (void)llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumU8CodeUnits,
1074 &ToPtr, ToPtr + NumU8CodeUnits, llvm::strictConversion);
1075 uint32_t StringLength = ToPtr - &ToBuf[0];
1079 Fields.
addInt(Int32Ty, 2);
1081 Fields.
addInt(Int32Ty, StringLength);
1083 Fields.
addInt(Int32Ty, StringLength * 2);
1085 Fields.
addInt(Int32Ty, 0);
1087 auto Arr = llvm::ArrayRef(&ToBuf[0], ToPtr + 1);
1088 auto *
C = llvm::ConstantDataArray::get(VMContext, Arr);
1089 auto *Buffer =
new llvm::GlobalVariable(TheModule,
C->getType(),
1090 true, llvm::GlobalValue::PrivateLinkage,
C,
".str");
1091 Buffer->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1095 Fields.
addInt(Int32Ty, 0);
1097 Fields.
addInt(Int32Ty, Str.size());
1099 Fields.
addInt(Int32Ty, Str.size());
1101 Fields.
addInt(Int32Ty, 0);
1103 Fields.
add(MakeConstantString(Str));
1105 std::string StringName;
1108 StringName =
".objc_str_";
1109 for (
unsigned char c : Str) {
1120 llvm::GlobalVariable *ObjCStrGV =
1122 isNamed ? StringRef(StringName) :
".objc_string",
1123 Align,
false,
isNamed ? llvm::GlobalValue::LinkOnceODRLinkage
1124 : llvm::GlobalValue::PrivateLinkage);
1125 ObjCStrGV->setSection(sectionName<ConstantStringSection>());
1127 ObjCStrGV->setComdat(TheModule.getOrInsertComdat(StringName));
1128 ObjCStrGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1130 if (CGM.
getTriple().isOSBinFormatCOFF()) {
1131 std::pair<llvm::GlobalVariable*, int> v{ObjCStrGV, 0};
1132 EarlyInitList.emplace_back(Sym, v);
1134 ObjCStrings[Str] = ObjCStrGV;
1135 ConstantStrings.push_back(ObjCStrGV);
1136 return ConstantAddress(ObjCStrGV, IdElemTy, Align);
1139 void PushProperty(ConstantArrayBuilder &PropertiesArray,
1140 const ObjCPropertyDecl *property,
1142 bool isSynthesized=
true,
bool
1143 isDynamic=
true)
override {
1152 auto Fields = PropertiesArray.
beginStruct(PropertyMetadataTy);
1155 std::string TypeStr =
1157 Fields.
add(MakeConstantString(TypeStr));
1158 std::string typeStr;
1160 Fields.
add(MakeConstantString(typeStr));
1161 auto addPropertyMethod = [&](
const ObjCMethodDecl *accessor) {
1164 Fields.
add(GetConstantSelector(accessor->getSelector(), TypeStr));
1166 Fields.
add(NULLPtr);
1175 GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods)
override {
1181 llvm::StructType *ObjCMethodDescTy =
1183 { PtrToInt8Ty, PtrToInt8Ty });
1185 ConstantInitBuilder Builder(CGM);
1192 auto MethodList = Builder.beginStruct();
1194 MethodList.addInt(IntTy, Methods.size());
1196 const llvm::DataLayout &DL = TheModule.getDataLayout();
1197 MethodList.addInt(IntTy, DL.getTypeSizeInBits(ObjCMethodDescTy) /
1200 auto MethodArray = MethodList.beginArray(ObjCMethodDescTy);
1201 for (
auto *M : Methods) {
1202 auto Method = MethodArray.beginStruct(ObjCMethodDescTy);
1203 Method.add(CGObjCGNU::GetConstantSelector(M));
1205 Method.finishAndAddTo(MethodArray);
1207 MethodArray.finishAndAddTo(MethodList);
1208 return MethodList.finishAndCreateGlobal(
".objc_protocol_method_list",
1211 llvm::Constant *GenerateCategoryProtocolList(
const ObjCCategoryDecl *OCD)
1214 auto RuntimeProtocols = GetRuntimeProtocolList(ReferencedProtocols.begin(),
1215 ReferencedProtocols.end());
1216 SmallVector<llvm::Constant *, 16> Protocols;
1217 for (
const auto *PI : RuntimeProtocols)
1218 Protocols.push_back(GenerateProtocolRef(PI));
1219 return GenerateProtocolList(Protocols);
1222 llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
1223 llvm::Value *cmd, MessageSendInfo &MSI)
override {
1225 CGBuilderTy &Builder = CGF.
Builder;
1226 llvm::Value *lookupArgs[] = {
1233 llvm::GlobalVariable *GetClassVar(StringRef Name,
bool isWeak=
false) {
1234 std::string SymbolName = SymbolForClassRef(Name, isWeak);
1235 auto *ClassSymbol = TheModule.getNamedGlobal(SymbolName);
1238 ClassSymbol =
new llvm::GlobalVariable(TheModule,
1239 IdTy,
false, llvm::GlobalValue::ExternalLinkage,
1240 nullptr, SymbolName);
1246 ClassSymbol->setInitializer(
new llvm::GlobalVariable(TheModule,
1247 Int8Ty,
false, llvm::GlobalValue::ExternalWeakLinkage,
1248 nullptr, SymbolForClass(Name)));
1250 if (CGM.
getTriple().isOSBinFormatCOFF()) {
1255 const ObjCInterfaceDecl *OID =
nullptr;
1257 if ((OID = dyn_cast<ObjCInterfaceDecl>(
Result)))
1263 assert(OID &&
"Failed to find ObjCInterfaceDecl");
1265 if (OIDDef !=
nullptr)
1268 auto Storage = llvm::GlobalValue::DefaultStorageClass;
1269 if (OID->
hasAttr<DLLImportAttr>())
1270 Storage = llvm::GlobalValue::DLLImportStorageClass;
1271 else if (OID->
hasAttr<DLLExportAttr>())
1272 Storage = llvm::GlobalValue::DLLExportStorageClass;
1277 assert(ClassSymbol->getName() == SymbolName);
1280 llvm::Value *GetClassNamed(CodeGenFunction &CGF,
1281 const std::string &Name,
1282 bool isWeak)
override {
1294 switch (Ownership) {
1311 llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
1312 ArrayRef<llvm::Constant *> IvarTypes,
1313 ArrayRef<llvm::Constant *> IvarOffsets,
1314 ArrayRef<llvm::Constant *> IvarAlign,
1315 ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership)
override {
1316 llvm_unreachable(
"Method should not be called!");
1319 llvm::Constant *GenerateEmptyProtocol(StringRef ProtocolName)
override {
1320 std::string Name = SymbolForProtocol(ProtocolName);
1321 auto *GV = TheModule.getGlobalVariable(Name);
1324 GV =
new llvm::GlobalVariable(TheModule, ProtocolTy,
false,
1325 llvm::GlobalValue::ExternalLinkage,
nullptr, Name);
1332 llvm::StringMap<llvm::Constant*> ExistingProtocolRefs;
1334 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1335 const ObjCProtocolDecl *PD)
override {
1337 auto *&Ref = ExistingProtocolRefs[Name];
1339 auto *&
Protocol = ExistingProtocols[Name];
1341 Protocol = GenerateProtocolRef(PD);
1342 std::string RefName = SymbolForProtocolRef(Name);
1343 assert(!TheModule.getGlobalVariable(RefName));
1345 auto GV =
new llvm::GlobalVariable(TheModule, ProtocolPtrTy,
false,
1346 llvm::GlobalValue::LinkOnceODRLinkage,
1348 GV->setComdat(TheModule.getOrInsertComdat(RefName));
1349 GV->setSection(sectionName<ProtocolReferenceSection>());
1353 EmittedProtocolRef =
true;
1358 llvm::Constant *GenerateProtocolList(ArrayRef<llvm::Constant*> Protocols) {
1359 llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(ProtocolPtrTy,
1361 llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
1363 ConstantInitBuilder builder(CGM);
1364 auto ProtocolBuilder = builder.beginStruct();
1365 ProtocolBuilder.addNullPointer(PtrTy);
1366 ProtocolBuilder.addInt(SizeTy, Protocols.size());
1367 ProtocolBuilder.add(ProtocolArray);
1368 return ProtocolBuilder.finishAndCreateGlobal(
".objc_protocol_list",
1372 void GenerateProtocol(
const ObjCProtocolDecl *PD)
override {
1375 llvm::Constant *GenerateProtocolRef(
const ObjCProtocolDecl *PD)
override {
1377 auto *&
Protocol = ExistingProtocols[ProtocolName];
1381 EmittedProtocol =
true;
1383 auto SymName = SymbolForProtocol(ProtocolName);
1384 auto *OldGV = TheModule.getGlobalVariable(SymName);
1394 Protocol =
new llvm::GlobalVariable(TheModule, ProtocolTy,
1396 llvm::GlobalValue::ExternalLinkage,
nullptr, SymName);
1400 SmallVector<llvm::Constant*, 16> Protocols;
1401 auto RuntimeProtocols =
1403 for (
const auto *PI : RuntimeProtocols)
1404 Protocols.push_back(GenerateProtocolRef(PI));
1405 llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
1408 llvm::Constant *InstanceMethodList, *OptionalInstanceMethodList;
1409 llvm::Constant *ClassMethodList, *OptionalClassMethodList;
1411 OptionalInstanceMethodList);
1412 EmitProtocolMethodList(PD->
class_methods(), ClassMethodList,
1413 OptionalClassMethodList);
1417 ConstantInitBuilder builder(CGM);
1418 auto ProtocolBuilder = builder.beginStruct();
1419 ProtocolBuilder.add(llvm::ConstantExpr::getIntToPtr(
1420 llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
1421 ProtocolBuilder.add(MakeConstantString(ProtocolName));
1422 ProtocolBuilder.add(ProtocolList);
1423 ProtocolBuilder.add(InstanceMethodList);
1424 ProtocolBuilder.add(ClassMethodList);
1425 ProtocolBuilder.add(OptionalInstanceMethodList);
1426 ProtocolBuilder.add(OptionalClassMethodList);
1428 ProtocolBuilder.add(GeneratePropertyList(
nullptr, PD,
false,
false));
1430 ProtocolBuilder.add(GeneratePropertyList(
nullptr, PD,
false,
true));
1432 ProtocolBuilder.add(GeneratePropertyList(
nullptr, PD,
true,
false));
1434 ProtocolBuilder.add(GeneratePropertyList(
nullptr, PD,
true,
true));
1436 auto *GV = ProtocolBuilder.finishAndCreateGlobal(SymName,
1438 GV->setSection(sectionName<ProtocolSection>());
1439 GV->setComdat(TheModule.getOrInsertComdat(SymName));
1441 OldGV->replaceAllUsesWith(GV);
1442 OldGV->removeFromParent();
1443 GV->setName(SymName);
1448 llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
1449 const std::string &TypeEncoding)
override {
1450 return GetConstantSelector(Sel, TypeEncoding);
1452 std::string GetSymbolNameForTypeEncoding(
const std::string &TypeEncoding) {
1453 std::string MangledTypes = std::string(TypeEncoding);
1459 llvm::replace(MangledTypes,
'@',
'\1');
1462 llvm::replace(MangledTypes,
'=',
'\2');
1463 return MangledTypes;
1465 llvm::Constant *GetTypeString(llvm::StringRef TypeEncoding) {
1466 if (TypeEncoding.empty())
1468 std::string MangledTypes =
1469 GetSymbolNameForTypeEncoding(std::string(TypeEncoding));
1470 std::string TypesVarName =
".objc_sel_types_" + MangledTypes;
1471 auto *TypesGlobal = TheModule.getGlobalVariable(TypesVarName);
1473 llvm::Constant *
Init = llvm::ConstantDataArray::getString(VMContext,
1475 auto *GV =
new llvm::GlobalVariable(TheModule,
Init->getType(),
1476 true, llvm::GlobalValue::LinkOnceODRLinkage,
Init, TypesVarName);
1477 GV->setComdat(TheModule.getOrInsertComdat(TypesVarName));
1478 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1483 llvm::Constant *GetConstantSelector(Selector Sel,
1484 const std::string &TypeEncoding)
override {
1485 std::string MangledTypes = GetSymbolNameForTypeEncoding(TypeEncoding);
1486 auto SelVarName = (StringRef(
".objc_selector_") + Sel.
getAsString() +
"_" +
1487 MangledTypes).str();
1488 if (
auto *GV = TheModule.getNamedGlobal(SelVarName))
1490 ConstantInitBuilder builder(CGM);
1491 auto SelBuilder = builder.beginStruct();
1492 SelBuilder.add(ExportUniqueString(Sel.
getAsString(),
".objc_sel_name_",
1494 SelBuilder.add(GetTypeString(TypeEncoding));
1495 auto *GV = SelBuilder.finishAndCreateGlobal(SelVarName,
1497 GV->setComdat(TheModule.getOrInsertComdat(SelVarName));
1498 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1499 GV->setSection(sectionName<SelectorSection>());
1502 llvm::StructType *emptyStruct =
nullptr;
1511 std::pair<llvm::Constant*,llvm::Constant*>
1512 GetSectionBounds(StringRef Section) {
1513 if (CGM.
getTriple().isOSBinFormatCOFF()) {
1514 if (emptyStruct ==
nullptr) {
1515 emptyStruct = llvm::StructType::create(
1516 VMContext, {},
".objc_section_sentinel",
true);
1518 auto ZeroInit = llvm::Constant::getNullValue(emptyStruct);
1519 auto Sym = [&](StringRef Prefix, StringRef SecSuffix) {
1520 auto *Sym =
new llvm::GlobalVariable(TheModule, emptyStruct,
1522 llvm::GlobalValue::LinkOnceODRLinkage, ZeroInit, Prefix +
1524 Sym->setVisibility(llvm::GlobalValue::HiddenVisibility);
1525 Sym->setSection((Section + SecSuffix).str());
1526 Sym->setComdat(TheModule.getOrInsertComdat((Prefix +
1531 return { Sym(
"__start_",
"$a"), Sym(
"__stop",
"$z") };
1533 auto *Start =
new llvm::GlobalVariable(TheModule, PtrTy,
1535 llvm::GlobalValue::ExternalLinkage,
nullptr, StringRef(
"__start_") +
1537 Start->setVisibility(llvm::GlobalValue::HiddenVisibility);
1538 auto *Stop =
new llvm::GlobalVariable(TheModule, PtrTy,
1540 llvm::GlobalValue::ExternalLinkage,
nullptr, StringRef(
"__stop_") +
1542 Stop->setVisibility(llvm::GlobalValue::HiddenVisibility);
1543 return { Start, Stop };
1545 CatchTypeInfo getCatchAllTypeInfo()
override {
1548 llvm::Function *ModuleInitFunction()
override {
1549 llvm::Function *LoadFunction = llvm::Function::Create(
1550 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
false),
1551 llvm::GlobalValue::LinkOnceODRLinkage,
".objcv2_load_function",
1553 LoadFunction->setVisibility(llvm::GlobalValue::HiddenVisibility);
1554 LoadFunction->setComdat(TheModule.getOrInsertComdat(
".objcv2_load_function"));
1556 llvm::BasicBlock *EntryBB =
1557 llvm::BasicBlock::Create(VMContext,
"entry", LoadFunction);
1558 CGBuilderTy B(CGM, VMContext);
1559 B.SetInsertPoint(EntryBB);
1560 ConstantInitBuilder builder(CGM);
1561 auto InitStructBuilder = builder.beginStruct();
1562 InitStructBuilder.addInt(Int64Ty, 0);
1563 auto §ionVec = CGM.
getTriple().isOSBinFormatCOFF() ? PECOFFSectionsBaseNames : SectionsBaseNames;
1564 for (
auto *
s : sectionVec) {
1565 auto bounds = GetSectionBounds(
s);
1566 InitStructBuilder.add(bounds.first);
1567 InitStructBuilder.add(bounds.second);
1569 auto *InitStruct = InitStructBuilder.finishAndCreateGlobal(
".objc_init",
1571 InitStruct->setVisibility(llvm::GlobalValue::HiddenVisibility);
1572 InitStruct->setComdat(TheModule.getOrInsertComdat(
".objc_init"));
1574 CallRuntimeFunction(B,
"__objc_load", {InitStruct});;
1581 auto *InitVar =
new llvm::GlobalVariable(TheModule, LoadFunction->getType(),
1582 false, llvm::GlobalValue::LinkOnceAnyLinkage,
1583 LoadFunction,
".objc_ctor");
1586 assert(InitVar->getName() ==
".objc_ctor");
1592 if (CGM.
getTriple().isOSBinFormatCOFF())
1593 InitVar->setSection(
".CRT$XCLz");
1597 InitVar->setSection(
".init_array");
1599 InitVar->setSection(
".ctors");
1601 InitVar->setVisibility(llvm::GlobalValue::HiddenVisibility);
1602 InitVar->setComdat(TheModule.getOrInsertComdat(
".objc_ctor"));
1604 for (
auto *
C : Categories) {
1606 Cat->setSection(sectionName<CategorySection>());
1609 auto createNullGlobal = [&](StringRef Name, ArrayRef<llvm::Constant*>
Init,
1610 StringRef Section) {
1611 auto nullBuilder = builder.beginStruct();
1612 for (
auto *F :
Init)
1614 auto GV = nullBuilder.finishAndCreateGlobal(Name, CGM.
getPointerAlign(),
1615 false, llvm::GlobalValue::LinkOnceODRLinkage);
1616 GV->setSection(Section);
1617 GV->setComdat(TheModule.getOrInsertComdat(Name));
1618 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1622 for (
auto clsAlias : ClassAliases)
1623 createNullGlobal(std::string(
".objc_class_alias") +
1624 clsAlias.second, { MakeConstantString(clsAlias.second),
1625 GetClassVar(clsAlias.first) }, sectionName<ClassAliasSection>());
1630 if (!CGM.
getTriple().isOSBinFormatCOFF()) {
1631 createNullGlobal(
".objc_null_selector", {NULLPtr, NULLPtr},
1632 sectionName<SelectorSection>());
1633 if (Categories.empty())
1634 createNullGlobal(
".objc_null_category", {NULLPtr, NULLPtr,
1635 NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr},
1636 sectionName<CategorySection>());
1637 if (!EmittedClass) {
1638 createNullGlobal(
".objc_null_cls_init_ref", NULLPtr,
1639 sectionName<ClassSection>());
1640 createNullGlobal(
".objc_null_class_ref", { NULLPtr, NULLPtr },
1641 sectionName<ClassReferenceSection>());
1643 if (!EmittedProtocol)
1644 createNullGlobal(
".objc_null_protocol", {NULLPtr, NULLPtr, NULLPtr,
1645 NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr,
1646 NULLPtr}, sectionName<ProtocolSection>());
1647 if (!EmittedProtocolRef)
1648 createNullGlobal(
".objc_null_protocol_ref", {NULLPtr},
1649 sectionName<ProtocolReferenceSection>());
1650 if (ClassAliases.empty())
1651 createNullGlobal(
".objc_null_class_alias", { NULLPtr, NULLPtr },
1652 sectionName<ClassAliasSection>());
1653 if (ConstantStrings.empty()) {
1654 auto i32Zero = llvm::ConstantInt::get(Int32Ty, 0);
1655 createNullGlobal(
".objc_null_constant_string", { NULLPtr, i32Zero,
1656 i32Zero, i32Zero, i32Zero, NULLPtr },
1657 sectionName<ConstantStringSection>());
1660 ConstantStrings.clear();
1664 if (EarlyInitList.size() > 0) {
1665 auto *
Init = llvm::Function::Create(llvm::FunctionType::get(CGM.
VoidTy,
1666 {}), llvm::GlobalValue::InternalLinkage,
".objc_early_init",
1668 llvm::IRBuilder<>
b(llvm::BasicBlock::Create(CGM.
getLLVMContext(),
"entry",
1670 for (
const auto &lateInit : EarlyInitList) {
1671 auto *global = TheModule.getGlobalVariable(lateInit.first);
1673 llvm::GlobalVariable *GV = lateInit.second.first;
1674 b.CreateAlignedStore(
1676 b.CreateStructGEP(GV->getValueType(), GV, lateInit.second.second),
1683 auto *InitVar =
new llvm::GlobalVariable(CGM.
getModule(),
Init->getType(),
1684 true, llvm::GlobalValue::InternalLinkage,
1685 Init,
".objc_early_init_ptr");
1686 InitVar->setSection(
".CRT$XCLb");
1693 std::string GetIVarOffsetVariableName(
const ObjCInterfaceDecl *ID,
1694 const ObjCIvarDecl *Ivar)
override {
1695 std::string TypeEncoding;
1697 TypeEncoding = GetSymbolNameForTypeEncoding(TypeEncoding);
1698 const std::string Name =
"__objc_ivar_offset_" +
ID->getNameAsString()
1702 llvm::Value *EmitIvarOffset(CodeGenFunction &CGF,
1704 const ObjCIvarDecl *Ivar)
override {
1705 const ObjCInterfaceDecl *ContainingInterface =
1707 const std::string Name =
1708 GetIVarOffsetVariableName(ContainingInterface, Ivar);
1709 llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
1710 if (!IvarOffsetPointer) {
1711 IvarOffsetPointer =
new llvm::GlobalVariable(TheModule, IntTy,
false,
1712 llvm::GlobalValue::ExternalLinkage,
nullptr, Name);
1718 llvm::Value *Offset =
1720 if (Offset->getType() != PtrDiffTy)
1721 Offset = CGF.
Builder.CreateZExtOrBitCast(Offset, PtrDiffTy);
1724 void GenerateClass(
const ObjCImplementationDecl *OID)
override {
1726 bool IsCOFF = CGM.
getTriple().isOSBinFormatCOFF();
1729 ObjCInterfaceDecl *classDecl =
1732 auto *classNameConstant = MakeConstantString(className);
1734 ConstantInitBuilder builder(CGM);
1735 auto metaclassFields = builder.beginStruct();
1737 metaclassFields.addNullPointer(PtrTy);
1739 metaclassFields.addNullPointer(PtrTy);
1741 metaclassFields.add(classNameConstant);
1743 metaclassFields.addInt(LongTy, 0);
1746 metaclassFields.addInt(LongTy, ClassFlags::ClassFlagMeta);
1750 metaclassFields.addInt(LongTy, 0);
1752 metaclassFields.addNullPointer(PtrTy);
1757 metaclassFields.addNullPointer(PtrTy);
1759 SmallVector<ObjCMethodDecl*, 16> ClassMethods;
1762 metaclassFields.add(
1763 GenerateMethodList(className,
"", ClassMethods,
true));
1766 metaclassFields.addNullPointer(PtrTy);
1768 metaclassFields.addNullPointer(PtrTy);
1770 metaclassFields.addNullPointer(PtrTy);
1772 metaclassFields.addNullPointer(PtrTy);
1774 metaclassFields.addNullPointer(PtrTy);
1776 metaclassFields.addNullPointer(PtrTy);
1778 metaclassFields.addNullPointer(PtrTy);
1780 metaclassFields.addInt(LongTy, 0);
1782 metaclassFields.add(GeneratePropertyList(OID, classDecl,
true));
1784 auto *metaclass = metaclassFields.finishAndCreateGlobal(
1785 ManglePublicSymbol(
"OBJC_METACLASS_") + className,
1788 auto classFields = builder.beginStruct();
1790 classFields.add(metaclass);
1793 const ObjCInterfaceDecl * SuperClassDecl =
1795 llvm::Constant *SuperClass =
nullptr;
1796 if (SuperClassDecl) {
1797 auto SuperClassName = SymbolForClass(SuperClassDecl->
getNameAsString());
1798 SuperClass = TheModule.getNamedGlobal(SuperClassName);
1801 SuperClass =
new llvm::GlobalVariable(TheModule, PtrTy,
false,
1802 llvm::GlobalValue::ExternalLinkage,
nullptr, SuperClassName);
1804 auto Storage = llvm::GlobalValue::DefaultStorageClass;
1805 if (SuperClassDecl->
hasAttr<DLLImportAttr>())
1806 Storage = llvm::GlobalValue::DLLImportStorageClass;
1807 else if (SuperClassDecl->
hasAttr<DLLExportAttr>())
1808 Storage = llvm::GlobalValue::DLLExportStorageClass;
1814 classFields.add(SuperClass);
1816 classFields.addNullPointer(PtrTy);
1818 classFields.addNullPointer(PtrTy);
1820 classFields.
add(classNameConstant);
1822 classFields.addInt(LongTy, 0);
1825 classFields.addInt(LongTy, 0);
1827 int superInstanceSize = !SuperClassDecl ? 0 :
1840 classFields.addNullPointer(PtrTy);
1845 const llvm::DataLayout &DL = TheModule.getDataLayout();
1847 ConstantInitBuilder
b(CGM);
1848 auto ivarListBuilder =
b.beginStruct();
1850 ivarListBuilder.addInt(IntTy, ivar_count);
1852 llvm::StructType *ObjCIvarTy = llvm::StructType::get(
1858 ivarListBuilder.addInt(SizeTy, DL.getTypeSizeInBits(ObjCIvarTy) /
1861 auto ivarArrayBuilder = ivarListBuilder.beginArray();
1864 auto ivarTy = IVD->getType();
1865 auto ivarBuilder = ivarArrayBuilder.beginStruct();
1867 ivarBuilder.add(MakeConstantString(IVD->getNameAsString()));
1869 std::string TypeStr;
1872 ivarBuilder.add(MakeConstantString(TypeStr));
1874 uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
1875 uint64_t Offset = BaseOffset - superInstanceSize;
1876 llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset);
1877 std::string OffsetName = GetIVarOffsetVariableName(classDecl, IVD);
1878 llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName);
1880 OffsetVar->setInitializer(OffsetValue);
1882 OffsetVar =
new llvm::GlobalVariable(TheModule, IntTy,
1883 false, llvm::GlobalValue::ExternalLinkage,
1884 OffsetValue, OffsetName);
1885 auto ivarVisibility =
1889 llvm::GlobalValue::HiddenVisibility :
1890 llvm::GlobalValue::DefaultVisibility;
1891 OffsetVar->setVisibility(ivarVisibility);
1892 if (ivarVisibility != llvm::GlobalValue::HiddenVisibility)
1894 ivarBuilder.add(OffsetVar);
1896 ivarBuilder.addInt(Int32Ty,
1907 ivarBuilder.addInt(Int32Ty,
1908 (align << 3) | (1<<2) |
1909 FlagsForOwnership(ivarTy.getQualifiers().getObjCLifetime()));
1910 ivarBuilder.finishAndAddTo(ivarArrayBuilder);
1912 ivarArrayBuilder.finishAndAddTo(ivarListBuilder);
1913 auto ivarList = ivarListBuilder.finishAndCreateGlobal(
".objc_ivar_list",
1915 llvm::GlobalValue::PrivateLinkage);
1916 classFields.add(ivarList);
1919 SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
1920 InstanceMethods.insert(InstanceMethods.begin(), OID->
instmeth_begin(),
1923 if (propImpl->getPropertyImplementation() ==
1925 auto addIfExists = [&](
const ObjCMethodDecl *OMD) {
1926 if (OMD && OMD->hasBody())
1927 InstanceMethods.push_back(OMD);
1929 addIfExists(propImpl->getGetterMethodDecl());
1930 addIfExists(propImpl->getSetterMethodDecl());
1933 if (InstanceMethods.size() == 0)
1934 classFields.addNullPointer(PtrTy);
1937 GenerateMethodList(className,
"", InstanceMethods,
false));
1940 classFields.addNullPointer(PtrTy);
1942 classFields.addNullPointer(PtrTy);
1944 classFields.addNullPointer(PtrTy);
1946 classFields.addNullPointer(PtrTy);
1948 classFields.addNullPointer(PtrTy);
1950 auto RuntimeProtocols =
1953 SmallVector<llvm::Constant *, 16> Protocols;
1954 for (
const auto *I : RuntimeProtocols)
1955 Protocols.push_back(GenerateProtocolRef(I));
1957 if (Protocols.empty())
1958 classFields.addNullPointer(PtrTy);
1960 classFields.add(GenerateProtocolList(Protocols));
1962 classFields.addNullPointer(PtrTy);
1964 classFields.addInt(LongTy, 0);
1966 classFields.add(GeneratePropertyList(OID, classDecl));
1968 llvm::GlobalVariable *classStruct =
1969 classFields.finishAndCreateGlobal(SymbolForClass(className),
1972 auto *classRefSymbol = GetClassVar(className);
1973 classRefSymbol->setSection(sectionName<ClassReferenceSection>());
1974 classRefSymbol->setInitializer(classStruct);
1979 classStruct->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
1984 std::pair<llvm::GlobalVariable*, int> v{classStruct, 1};
1985 EarlyInitList.emplace_back(std::string(SuperClass->getName()),
1994 if (ClassPtrAlias) {
1995 ClassPtrAlias->replaceAllUsesWith(classStruct);
1996 ClassPtrAlias->eraseFromParent();
1997 ClassPtrAlias =
nullptr;
1999 if (
auto Placeholder =
2000 TheModule.getNamedGlobal(SymbolForClass(className)))
2001 if (Placeholder != classStruct) {
2002 Placeholder->replaceAllUsesWith(classStruct);
2003 Placeholder->eraseFromParent();
2004 classStruct->setName(SymbolForClass(className));
2006 if (MetaClassPtrAlias) {
2007 MetaClassPtrAlias->replaceAllUsesWith(metaclass);
2008 MetaClassPtrAlias->eraseFromParent();
2009 MetaClassPtrAlias =
nullptr;
2011 assert(classStruct->getName() == SymbolForClass(className));
2013 auto classInitRef =
new llvm::GlobalVariable(TheModule,
2014 classStruct->getType(),
false, llvm::GlobalValue::ExternalLinkage,
2015 classStruct, ManglePublicSymbol(
"OBJC_INIT_CLASS_") + className);
2016 classInitRef->setSection(sectionName<ClassSection>());
2019 EmittedClass =
true;
2022 CGObjCGNUstep2(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 10, 4, 2) {
2023 MsgLookupSuperFn.init(&CGM,
"objc_msg_lookup_super", IMPTy,
2024 PtrToObjCSuperTy, SelectorTy);
2025 SentInitializeFn.init(&CGM,
"objc_send_initialize",
2026 llvm::Type::getVoidTy(VMContext), IdTy);
2035 PropertyMetadataTy =
2037 { PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
2040 void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
2041 const ObjCMethodDecl *OMD,
2042 const ObjCContainerDecl *CD)
override {
2044 bool ReceiverCanBeNull =
true;
2046 auto selfValue = Builder.CreateLoad(selfAddr);
2071 ReceiverCanBeNull = isWeakLinkedClass(OID);
2075 if (ReceiverCanBeNull) {
2076 llvm::BasicBlock *SelfIsNilBlock =
2078 llvm::BasicBlock *ContBlock =
2083 auto Zero = llvm::ConstantPointerNull::get(selfTy);
2085 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue,
Zero),
2086 SelfIsNilBlock, ContBlock,
2087 MDHelper.createUnlikelyBranchWeights());
2093 Builder.SetInsertPoint(SelfIsNilBlock);
2094 if (!retTy->isVoidType()) {
2102 Builder.SetInsertPoint(ContBlock);
2108 llvm::StructType::get(PtrTy, PtrTy, PtrTy, LongTy, LongTy);
2115 llvm::Value *Val = Builder.CreateStructGEP(classStart, selfValue, 4);
2117 astContext.getTypeAlign(astContext.UnsignedLongTy));
2118 auto flags = Builder.CreateLoad(Address{Val, LongTy, Align});
2119 auto isInitialized =
2120 Builder.CreateAnd(flags, ClassFlags::ClassFlagInitialized);
2121 llvm::BasicBlock *notInitializedBlock =
2123 llvm::BasicBlock *initializedBlock =
2125 Builder.CreateCondBr(Builder.CreateICmpEQ(isInitialized, Zeros[0]),
2126 notInitializedBlock, initializedBlock,
2127 MDHelper.createUnlikelyBranchWeights());
2129 Builder.SetInsertPoint(notInitializedBlock);
2131 Builder.CreateBr(initializedBlock);
2133 Builder.SetInsertPoint(initializedBlock);
2141 Builder.CreateStore(GetSelector(CGF, OMD),
2147const char *
const CGObjCGNUstep2::SectionsBaseNames[8] =
2154"__objc_protocol_refs",
2155"__objc_class_aliases",
2156"__objc_constant_string"
2159const char *
const CGObjCGNUstep2::PECOFFSectionsBaseNames[8] =
2172class CGObjCObjFW:
public CGObjCGNU {
2176 LazyRuntimeFunction MsgLookupFn;
2179 LazyRuntimeFunction MsgLookupFnSRet;
2183 LazyRuntimeFunction MsgLookupSuperFn, MsgLookupSuperFnSRet;
2185 llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver,
2186 llvm::Value *cmd, llvm::MDNode *node,
2187 MessageSendInfo &MSI)
override {
2188 CGBuilderTy &Builder = CGF.
Builder;
2189 llvm::Value *args[] = {
2190 EnforceType(Builder, Receiver, IdTy),
2191 EnforceType(Builder, cmd, SelectorTy) };
2193 llvm::CallBase *imp;
2199 imp->setMetadata(msgSendMDKind, node);
2203 llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
2204 llvm::Value *cmd, MessageSendInfo &MSI)
override {
2205 CGBuilderTy &Builder = CGF.
Builder;
2206 llvm::Value *lookupArgs[] = {
2207 EnforceType(Builder, ObjCSuper.
emitRawPointer(CGF), PtrToObjCSuperTy),
2217 llvm::Value *GetClassNamed(CodeGenFunction &CGF,
const std::string &Name,
2218 bool isWeak)
override {
2220 return CGObjCGNU::GetClassNamed(CGF, Name, isWeak);
2223 std::string SymbolName =
"_OBJC_CLASS_" + Name;
2224 llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(SymbolName);
2226 ClassSymbol =
new llvm::GlobalVariable(TheModule, LongTy,
false,
2227 llvm::GlobalValue::ExternalLinkage,
2228 nullptr, SymbolName);
2232 void GenerateDirectMethodPrologue(
2233 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
2234 const ObjCContainerDecl *CD)
override {
2236 bool ReceiverCanBeNull =
true;
2238 auto selfValue = Builder.CreateLoad(selfAddr);
2257 "GenerateDirectMethod() should be called with the Class Interface");
2270 result = GeneratePossiblySpecializedMessageSend(
2271 CGF, ReturnValueSlot(), ResultType, SelfSel, selfValue, Args, OID,
2278 ReceiverCanBeNull = isWeakLinkedClass(OID);
2281 if (ReceiverCanBeNull) {
2282 llvm::BasicBlock *SelfIsNilBlock =
2284 llvm::BasicBlock *ContBlock =
2289 auto Zero = llvm::ConstantPointerNull::get(selfTy);
2292 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue,
Zero),
2293 SelfIsNilBlock, ContBlock,
2294 MDHelper.createUnlikelyBranchWeights());
2300 Builder.SetInsertPoint(SelfIsNilBlock);
2301 if (!retTy->isVoidType()) {
2309 Builder.SetInsertPoint(ContBlock);
2317 Builder.CreateStore(GetSelector(CGF, OMD),
2323 CGObjCObjFW(CodeGenModule &Mod): CGObjCGNU(Mod, 9, 3) {
2325 MsgLookupFn.init(&CGM,
"objc_msg_lookup", IMPTy, IdTy, SelectorTy);
2326 MsgLookupFnSRet.init(&CGM,
"objc_msg_lookup_stret", IMPTy, IdTy,
2329 MsgLookupSuperFn.init(&CGM,
"objc_msg_lookup_super", IMPTy,
2330 PtrToObjCSuperTy, SelectorTy);
2331 MsgLookupSuperFnSRet.init(&CGM,
"objc_msg_lookup_super_stret", IMPTy,
2332 PtrToObjCSuperTy, SelectorTy);
2340void CGObjCGNU::EmitClassRef(
const std::string &className) {
2341 std::string symbolRef =
"__objc_class_ref_" + className;
2343 if (TheModule.getGlobalVariable(symbolRef))
2345 std::string symbolName =
"__objc_class_name_" + className;
2346 llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName);
2348 ClassSymbol =
new llvm::GlobalVariable(TheModule, LongTy,
false,
2349 llvm::GlobalValue::ExternalLinkage,
2350 nullptr, symbolName);
2352 new llvm::GlobalVariable(TheModule, ClassSymbol->getType(),
true,
2353 llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef);
2356CGObjCGNU::CGObjCGNU(CodeGenModule &cgm,
unsigned runtimeABIVersion,
2357 unsigned protocolClassVersion,
unsigned classABI)
2358 : CGObjCRuntime(cgm), TheModule(CGM.getModule()),
2359 VMContext(cgm.getLLVMContext()), ClassPtrAlias(
nullptr),
2360 MetaClassPtrAlias(
nullptr), RuntimeVersion(runtimeABIVersion),
2361 ProtocolVersion(protocolClassVersion), ClassABIVersion(classABI) {
2363 msgSendMDKind = VMContext.getMDKindID(
"GNUObjCMessageSend");
2365 cgm.
getContext().getTargetInfo().getTriple().isWindowsMSVCEnvironment();
2367 cgm.
getContext().getTargetInfo().getTriple().isOSCygMing() &&
2381 Int8Ty = llvm::Type::getInt8Ty(VMContext);
2386 PtrToInt8Ty = PtrTy;
2387 ProtocolPtrTy = PtrTy;
2389 Zeros[0] = llvm::ConstantInt::get(LongTy, 0);
2390 Zeros[1] = Zeros[0];
2391 NULLPtr = llvm::ConstantPointerNull::get(PtrToInt8Ty);
2395 SelectorTy = PtrToInt8Ty;
2396 SelectorElemTy = Int8Ty;
2402 Int32Ty = llvm::Type::getInt32Ty(VMContext);
2403 Int64Ty = llvm::Type::getInt64Ty(VMContext);
2406 CGM.
getDataLayout().getPointerSizeInBits() == 32 ? Int32Ty : Int64Ty;
2421 ProtocolTy = llvm::StructType::get(IdTy,
2443 PropertyMetadataTy = llvm::StructType::get(CGM.
getLLVMContext(), {
2444 PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty,
2445 PtrToInt8Ty, PtrToInt8Ty });
2447 ObjCSuperTy = llvm::StructType::get(IdTy, IdTy);
2448 PtrToObjCSuperTy = PtrTy;
2450 llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
2453 ExceptionThrowFn.init(&CGM,
"objc_exception_throw", VoidTy, IdTy);
2454 ExceptionReThrowFn.init(&CGM,
2455 usesCxxExceptions ?
"objc_exception_rethrow"
2456 :
"objc_exception_throw",
2459 SyncEnterFn.init(&CGM,
"objc_sync_enter", IntTy, IdTy);
2461 SyncExitFn.init(&CGM,
"objc_sync_exit", IntTy, IdTy);
2464 EnumerationMutationFn.init(&CGM,
"objc_enumerationMutation", VoidTy, IdTy);
2467 GetPropertyFn.init(&CGM,
"objc_getProperty", IdTy, IdTy, SelectorTy,
2470 SetPropertyFn.init(&CGM,
"objc_setProperty", VoidTy, IdTy, SelectorTy,
2471 PtrDiffTy, IdTy, BoolTy, BoolTy);
2473 GetStructPropertyFn.init(&CGM,
"objc_getPropertyStruct", VoidTy, PtrTy, PtrTy,
2474 PtrDiffTy, BoolTy, BoolTy);
2476 SetStructPropertyFn.init(&CGM,
"objc_setPropertyStruct", VoidTy, PtrTy, PtrTy,
2477 PtrDiffTy, BoolTy, BoolTy);
2484 RuntimeVersion = 10;
2499 IvarAssignFn.init(&CGM,
"objc_assign_ivar", IdTy, IdTy, IdTy, PtrDiffTy);
2501 StrongCastAssignFn.init(&CGM,
"objc_assign_strongCast", IdTy, IdTy,
2504 GlobalAssignFn.init(&CGM,
"objc_assign_global", IdTy, IdTy, PtrToIdTy);
2506 WeakAssignFn.init(&CGM,
"objc_assign_weak", IdTy, IdTy, PtrToIdTy);
2508 WeakReadFn.init(&CGM,
"objc_read_weak", IdTy, PtrToIdTy);
2510 MemMoveFn.init(&CGM,
"objc_memmove_collectable", PtrTy, PtrTy, PtrTy,
2516 const std::string &Name,
bool isWeak) {
2517 llvm::Constant *ClassName = MakeConstantString(Name);
2529 llvm::FunctionType::get(IdTy, PtrToInt8Ty,
true),
"objc_lookup_class");
2535llvm::Value *CGObjCGNU::GetClass(CodeGenFunction &CGF,
2536 const ObjCInterfaceDecl *OID) {
2539 if (
auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(
Value))
2544llvm::Value *CGObjCGNU::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
2545 auto *
Value = GetClassNamed(CGF,
"NSAutoreleasePool",
false);
2546 if (CGM.
getTriple().isOSBinFormatCOFF()) {
2547 if (
auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(
Value)) {
2552 const VarDecl *VD =
nullptr;
2554 if ((VD = dyn_cast<VarDecl>(
Result)))
2563llvm::Value *CGObjCGNU::GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
2564 const std::string &TypeEncoding) {
2565 SmallVectorImpl<TypedSelector> &Types = SelectorTable[Sel];
2566 llvm::GlobalAlias *SelValue =
nullptr;
2568 for (
const TypedSelector &
Type : Types) {
2569 if (
Type.first == TypeEncoding) {
2570 SelValue =
Type.second;
2575 SelValue = llvm::GlobalAlias::create(SelectorElemTy, 0,
2576 llvm::GlobalValue::PrivateLinkage,
2579 Types.emplace_back(TypeEncoding, SelValue);
2585Address CGObjCGNU::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
2586 llvm::Value *SelValue = GetSelector(CGF, Sel);
2596llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel) {
2597 return GetTypedSelector(CGF, Sel, std::string());
2600llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF,
2601 const ObjCMethodDecl *
Method) {
2603 return GetTypedSelector(CGF,
Method->getSelector(), SelTypes);
2606llvm::Constant *CGObjCGNU::GetEHType(QualType
T) {
2613 return MakeConstantString(
"@id");
2620 const ObjCObjectPointerType *OPT =
T->
getAs<ObjCObjectPointerType>();
2621 assert(OPT &&
"Invalid @catch type.");
2622 const ObjCInterfaceDecl *IDecl = OPT->
getObjectType()->getInterface();
2623 assert(IDecl &&
"Invalid @catch type.");
2627llvm::Constant *CGObjCGNUstep::GetEHType(QualType
T) {
2628 if (usesSEHExceptions)
2631 if (!CGM.
getLangOpts().CPlusPlus && !usesCxxExceptions)
2632 return CGObjCGNU::GetEHType(
T);
2640 llvm::Constant *IDEHType =
2641 CGM.
getModule().getGlobalVariable(
"__objc_id_type_info");
2644 new llvm::GlobalVariable(CGM.
getModule(), PtrToInt8Ty,
2646 llvm::GlobalValue::ExternalLinkage,
2647 nullptr,
"__objc_id_type_info");
2651 const ObjCObjectPointerType *PT =
2652 T->
getAs<ObjCObjectPointerType>();
2653 assert(PT &&
"Invalid @catch type.");
2655 assert(IT &&
"Invalid @catch type.");
2656 std::string className =
2659 std::string typeinfoName =
"__objc_eh_typeinfo_" + className;
2662 if (llvm::Constant *typeinfo = TheModule.getGlobalVariable(typeinfoName))
2670 const char *vtableName =
"_ZTVN7gnustep7libobjc22__objc_class_type_infoE";
2671 auto *Vtable = TheModule.getGlobalVariable(vtableName);
2673 Vtable =
new llvm::GlobalVariable(TheModule, PtrToInt8Ty,
true,
2674 llvm::GlobalValue::ExternalLinkage,
2675 nullptr, vtableName);
2677 llvm::Constant *Two = llvm::ConstantInt::get(IntTy, 2);
2679 llvm::ConstantExpr::getGetElementPtr(Vtable->getValueType(), Vtable, Two);
2681 llvm::Constant *typeName =
2682 ExportUniqueString(className,
"__objc_eh_typename_");
2684 ConstantInitBuilder builder(CGM);
2685 auto fields = builder.beginStruct();
2686 fields.add(BVtable);
2687 fields.add(typeName);
2688 llvm::Constant *TI =
2689 fields.finishAndCreateGlobal(
"__objc_eh_typeinfo_" + className,
2692 llvm::GlobalValue::LinkOnceODRLinkage);
2697ConstantAddress CGObjCGNU::GenerateConstantString(
const StringLiteral *SL) {
2699 std::string Str = SL->
getString().str();
2703 llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
2704 if (old != ObjCStrings.end())
2705 return ConstantAddress(old->getValue(), Int8Ty, Align);
2709 if (StringClass.empty()) StringClass =
"NSConstantString";
2711 std::string Sym =
"_OBJC_CLASS_";
2714 llvm::Constant *
isa = TheModule.getNamedGlobal(Sym);
2717 isa =
new llvm::GlobalVariable(TheModule, IdTy,
false,
2718 llvm::GlobalValue::ExternalWeakLinkage,
2721 ConstantInitBuilder Builder(CGM);
2722 auto Fields = Builder.beginStruct();
2724 Fields.
add(MakeConstantString(Str));
2725 Fields.
addInt(IntTy, Str.size());
2727 ObjCStrings[Str] = ObjCStr;
2728 ConstantStrings.push_back(ObjCStr);
2729 return ConstantAddress(ObjCStr, Int8Ty, Align);
2736CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF,
2737 ReturnValueSlot Return,
2738 QualType ResultType,
2740 const ObjCInterfaceDecl *
Class,
2741 bool isCategoryImpl,
2742 llvm::Value *Receiver,
2743 bool IsClassMessage,
2744 const CallArgList &CallArgs,
2745 const ObjCMethodDecl *
Method) {
2746 CGBuilderTy &Builder = CGF.
Builder;
2747 if (CGM.
getLangOpts().getGC() == LangOptions::GCOnly) {
2748 if (Sel == RetainSel || Sel == AutoreleaseSel) {
2752 if (Sel == ReleaseSel) {
2757 llvm::Value *cmd = GetSelector(CGF, Sel);
2758 CallArgList ActualArgs;
2760 ActualArgs.
add(
RValue::get(EnforceType(Builder, Receiver, IdTy)), ASTIdTy);
2764 MessageSendInfo MSI = getMessageSendInfo(
Method, ResultType, ActualArgs);
2766 llvm::Value *ReceiverClass =
nullptr;
2769 ReceiverClass = GetClassNamed(CGF,
2770 Class->getSuperClass()->getNameAsString(),
false);
2771 if (IsClassMessage) {
2774 Builder.CreateAlignedLoad(IdTy, ReceiverClass, CGF.
getPointerAlign());
2776 ReceiverClass = EnforceType(Builder, ReceiverClass, IdTy);
2778 if (isCategoryImpl) {
2779 llvm::FunctionCallee classLookupFunction =
nullptr;
2780 if (IsClassMessage) {
2782 IdTy, PtrTy,
true),
"objc_get_meta_class");
2785 IdTy, PtrTy,
true),
"objc_get_class");
2787 ReceiverClass = Builder.CreateCall(classLookupFunction,
2788 MakeConstantString(
Class->getNameAsString()));
2795 if (IsClassMessage) {
2796 if (!MetaClassPtrAlias) {
2797 MetaClassPtrAlias = llvm::GlobalAlias::create(
2798 IdElemTy, 0, llvm::GlobalValue::InternalLinkage,
2799 ".objc_metaclass_ref" +
Class->getNameAsString(), &TheModule);
2801 ReceiverClass = MetaClassPtrAlias;
2803 if (!ClassPtrAlias) {
2804 ClassPtrAlias = llvm::GlobalAlias::create(
2805 IdElemTy, 0, llvm::GlobalValue::InternalLinkage,
2806 ".objc_class_ref" +
Class->getNameAsString(), &TheModule);
2808 ReceiverClass = ClassPtrAlias;
2812 llvm::Type *CastTy = llvm::StructType::get(IdTy, IdTy);
2814 ReceiverClass = Builder.CreateStructGEP(CastTy, ReceiverClass, 1);
2817 Builder.CreateAlignedLoad(IdTy, ReceiverClass, CGF.
getPointerAlign());
2820 llvm::StructType *ObjCSuperTy =
2821 llvm::StructType::get(Receiver->getType(), IdTy);
2826 Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0));
2827 Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1));
2830 llvm::Value *imp = LookupIMPSuper(CGF, ObjCSuper, cmd, MSI);
2831 imp = EnforceType(Builder, imp, MSI.MessengerType);
2833 llvm::Metadata *impMD[] = {
2834 llvm::MDString::get(VMContext, Sel.
getAsString()),
2835 llvm::MDString::get(VMContext,
Class->getSuperClass()->getNameAsString()),
2836 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2837 llvm::Type::getInt1Ty(VMContext), IsClassMessage))};
2838 llvm::MDNode *
node = llvm::MDNode::get(VMContext, impMD);
2840 CGCallee callee(CGCalleeInfo(), imp);
2842 llvm::CallBase *call;
2843 RValue msgRet = CGF.
EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
2844 call->setMetadata(msgSendMDKind, node);
2850CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
2851 ReturnValueSlot Return,
2852 QualType ResultType,
2854 llvm::Value *Receiver,
2855 const CallArgList &CallArgs,
2856 const ObjCInterfaceDecl *
Class,
2857 const ObjCMethodDecl *
Method) {
2858 CGBuilderTy &Builder = CGF.
Builder;
2861 if (CGM.
getLangOpts().getGC() == LangOptions::GCOnly) {
2862 if (Sel == RetainSel || Sel == AutoreleaseSel) {
2866 if (Sel == ReleaseSel) {
2877 cmd = GetSelector(CGF,
Method);
2879 cmd = GetSelector(CGF, Sel);
2880 cmd = EnforceType(Builder, cmd, SelectorTy);
2883 Receiver = EnforceType(Builder, Receiver, IdTy);
2885 llvm::Metadata *impMD[] = {
2886 llvm::MDString::get(VMContext, Sel.
getAsString()),
2887 llvm::MDString::get(VMContext,
Class ?
Class->getNameAsString() :
""),
2888 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2889 llvm::Type::getInt1Ty(VMContext),
Class !=
nullptr))};
2890 llvm::MDNode *
node = llvm::MDNode::get(VMContext, impMD);
2892 CallArgList ActualArgs;
2898 MessageSendInfo MSI = getMessageSendInfo(
Method, ResultType, ActualArgs);
2919 bool hasParamDestroyedInCallee =
false;
2920 bool requiresExplicitZeroResult =
false;
2921 bool requiresNilReceiverCheck = [&] {
2923 if (!canMessageReceiverBeNull(CGF,
Method,
false,
2929 hasParamDestroyedInCallee =
true;
2950 requiresExplicitZeroResult = !isDirect;
2954 return hasParamDestroyedInCallee || requiresExplicitZeroResult;
2960 bool requiresExplicitAggZeroing =
2964 llvm::BasicBlock *continueBB =
nullptr;
2966 llvm::BasicBlock *nilPathBB =
nullptr;
2968 llvm::BasicBlock *nilCleanupBB =
nullptr;
2971 if (requiresNilReceiverCheck) {
2978 if (requiresExplicitAggZeroing || hasParamDestroyedInCallee) {
2981 nilPathBB = Builder.GetInsertBlock();
2984 llvm::Value *isNil = Builder.CreateICmpEQ(Receiver,
2985 llvm::Constant::getNullValue(Receiver->getType()));
2986 Builder.CreateCondBr(isNil, nilCleanupBB ? nilCleanupBB : continueBB,
2996 imp = GenerateMethod(
Method,
Method->getClassInterface());
3003 imp = LookupIMP(CGF, Receiver, cmd, node, MSI);
3007 StringRef
name =
"objc_msgSend";
3009 name =
"objc_msgSend_fpret";
3011 name =
"objc_msgSend_stret";
3015 bool shouldCheckForInReg =
3019 .isWindowsMSVCEnvironment() &&
3022 name =
"objc_msgSend_stret2";
3033 ActualArgs[0] = CallArg(
RValue::get(Receiver), ASTIdTy);
3035 imp = EnforceType(Builder, imp, MSI.MessengerType);
3037 llvm::CallBase *call;
3038 CGCallee callee(CGCalleeInfo(), imp);
3039 RValue msgRet = CGF.
EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
3041 call->setMetadata(msgSendMDKind, node);
3043 if (requiresNilReceiverCheck) {
3044 llvm::BasicBlock *nonNilPathBB = CGF.
Builder.GetInsertBlock();
3045 CGF.
Builder.CreateBr(continueBB);
3051 if (hasParamDestroyedInCallee) {
3052 destroyCalleeDestroyedArguments(CGF,
Method, CallArgs);
3055 if (requiresExplicitAggZeroing) {
3061 nilPathBB = CGF.
Builder.GetInsertBlock();
3062 CGF.
Builder.CreateBr(continueBB);
3070 llvm::PHINode *phi = Builder.CreatePHI(v->getType(), 2);
3071 phi->addIncoming(v, nonNilPathBB);
3078 std::pair<llvm::Value*,llvm::Value*> v = msgRet.
getComplexVal();
3079 llvm::PHINode *phi = Builder.CreatePHI(v.first->getType(), 2);
3080 phi->addIncoming(v.first, nonNilPathBB);
3081 phi->addIncoming(llvm::Constant::getNullValue(v.first->getType()),
3083 llvm::PHINode *phi2 = Builder.CreatePHI(v.second->getType(), 2);
3084 phi2->addIncoming(v.second, nonNilPathBB);
3085 phi2->addIncoming(llvm::Constant::getNullValue(v.second->getType()),
3095llvm::Constant *CGObjCGNU::
3096GenerateMethodList(StringRef ClassName,
3097 StringRef CategoryName,
3098 ArrayRef<const ObjCMethodDecl*> Methods,
3099 bool isClassMethodList) {
3100 if (Methods.empty())
3103 ConstantInitBuilder Builder(CGM);
3105 auto MethodList = Builder.beginStruct();
3106 MethodList.addNullPointer(CGM.
Int8PtrTy);
3107 MethodList.addInt(Int32Ty, Methods.size());
3110 llvm::StructType *ObjCMethodTy =
3119 const llvm::DataLayout &DL = TheModule.getDataLayout();
3120 MethodList.addInt(SizeTy, DL.getTypeSizeInBits(ObjCMethodTy) /
3136 auto MethodArray = MethodList.beginArray();
3138 for (
const auto *OMD : Methods) {
3139 llvm::Constant *FnPtr =
3140 TheModule.getFunction(getSymbolNameForMethod(OMD));
3141 assert(FnPtr &&
"Can't generate metadata for method that doesn't exist");
3142 auto Method = MethodArray.beginStruct(ObjCMethodTy);
3153 Method.finishAndAddTo(MethodArray);
3155 MethodArray.finishAndAddTo(MethodList);
3158 return MethodList.finishAndCreateGlobal(
".objc_method_list",
3163llvm::Constant *CGObjCGNU::
3164GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
3165 ArrayRef<llvm::Constant *> IvarTypes,
3166 ArrayRef<llvm::Constant *> IvarOffsets,
3167 ArrayRef<llvm::Constant *> IvarAlign,
3168 ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership) {
3169 if (IvarNames.empty())
3172 ConstantInitBuilder Builder(CGM);
3175 auto IvarList = Builder.beginStruct();
3176 IvarList.addInt(IntTy, (
int)IvarNames.size());
3179 llvm::StructType *ObjCIvarTy =
3180 llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy);
3183 auto Ivars = IvarList.beginArray(ObjCIvarTy);
3184 for (
unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
3185 auto Ivar = Ivars.beginStruct(ObjCIvarTy);
3186 Ivar.
add(IvarNames[i]);
3187 Ivar.
add(IvarTypes[i]);
3188 Ivar.
add(IvarOffsets[i]);
3189 Ivar.finishAndAddTo(Ivars);
3191 Ivars.finishAndAddTo(IvarList);
3194 return IvarList.finishAndCreateGlobal(
".objc_ivar_list",
3199llvm::Constant *CGObjCGNU::GenerateClassStructure(
3200 llvm::Constant *MetaClass,
3201 llvm::Constant *SuperClass,
3204 llvm::Constant *Version,
3205 llvm::Constant *InstanceSize,
3206 llvm::Constant *IVars,
3207 llvm::Constant *Methods,
3208 llvm::Constant *Protocols,
3209 llvm::Constant *IvarOffsets,
3210 llvm::Constant *Properties,
3211 llvm::Constant *StrongIvarBitmap,
3212 llvm::Constant *WeakIvarBitmap,
3221 llvm::StructType *ClassTy = llvm::StructType::get(
3238 IvarOffsets->getType(),
3239 Properties->getType(),
3244 ConstantInitBuilder Builder(CGM);
3245 auto Elements = Builder.beginStruct(ClassTy);
3250 Elements.add(MetaClass);
3252 Elements.add(SuperClass);
3254 Elements.add(MakeConstantString(Name,
".class_name"));
3256 Elements.addInt(LongTy, 0);
3258 Elements.addInt(LongTy, info);
3261 const llvm::DataLayout &DL = TheModule.getDataLayout();
3262 Elements.addInt(LongTy, DL.getTypeSizeInBits(ClassTy) /
3265 Elements.add(InstanceSize);
3267 Elements.add(IVars);
3269 Elements.add(Methods);
3272 Elements.add(NULLPtr);
3274 Elements.add(NULLPtr);
3276 Elements.add(NULLPtr);
3278 Elements.add(Protocols);
3280 Elements.add(NULLPtr);
3282 Elements.addInt(LongTy, ClassABIVersion);
3284 Elements.add(IvarOffsets);
3286 Elements.add(Properties);
3288 Elements.add(StrongIvarBitmap);
3290 Elements.add(WeakIvarBitmap);
3295 std::string ClassSym((isMeta ?
"_OBJC_METACLASS_":
"_OBJC_CLASS_") +
3297 llvm::GlobalVariable *ClassRef = TheModule.getNamedGlobal(ClassSym);
3298 llvm::Constant *
Class =
3299 Elements.finishAndCreateGlobal(ClassSym, CGM.
getPointerAlign(),
false,
3300 llvm::GlobalValue::ExternalLinkage);
3302 ClassRef->replaceAllUsesWith(
Class);
3303 ClassRef->removeFromParent();
3304 Class->setName(ClassSym);
3309llvm::Constant *CGObjCGNU::
3310GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods) {
3312 llvm::StructType *ObjCMethodDescTy =
3313 llvm::StructType::get(CGM.
getLLVMContext(), { PtrToInt8Ty, PtrToInt8Ty });
3315 ConstantInitBuilder Builder(CGM);
3316 auto MethodList = Builder.beginStruct();
3317 MethodList.addInt(IntTy, Methods.size());
3318 auto MethodArray = MethodList.beginArray(ObjCMethodDescTy);
3319 for (
auto *M : Methods) {
3320 auto Method = MethodArray.beginStruct(ObjCMethodDescTy);
3321 Method.add(MakeConstantString(M->getSelector().getAsString()));
3323 Method.finishAndAddTo(MethodArray);
3325 MethodArray.finishAndAddTo(MethodList);
3326 return MethodList.finishAndCreateGlobal(
".objc_method_list",
3332CGObjCGNU::GenerateProtocolList(ArrayRef<std::string> Protocols) {
3334 ConstantInitBuilder Builder(CGM);
3335 auto ProtocolList = Builder.beginStruct();
3336 ProtocolList.add(NULLPtr);
3337 ProtocolList.addInt(LongTy, Protocols.size());
3339 auto Elements = ProtocolList.beginArray(PtrToInt8Ty);
3340 for (
const std::string &Protocol : Protocols) {
3341 llvm::Constant *protocol =
nullptr;
3342 llvm::StringMap<llvm::Constant *>::iterator value =
3343 ExistingProtocols.find(Protocol);
3344 if (value == ExistingProtocols.end()) {
3345 protocol = GenerateEmptyProtocol(Protocol);
3347 protocol = value->getValue();
3349 Elements.add(protocol);
3351 Elements.finishAndAddTo(ProtocolList);
3352 return ProtocolList.finishAndCreateGlobal(
".objc_protocol_list",
3356llvm::Value *CGObjCGNU::GenerateProtocolRef(CodeGenFunction &CGF,
3357 const ObjCProtocolDecl *PD) {
3358 return GenerateProtocolRef(PD);
3361llvm::Constant *CGObjCGNU::GenerateProtocolRef(
const ObjCProtocolDecl *PD) {
3364 GenerateProtocol(PD);
3365 assert(protocol &&
"Unknown protocol");
3370CGObjCGNU::GenerateEmptyProtocol(StringRef ProtocolName) {
3371 llvm::Constant *ProtocolList = GenerateProtocolList({});
3372 llvm::Constant *MethodList = GenerateProtocolMethodList({});
3375 ConstantInitBuilder Builder(CGM);
3376 auto Elements = Builder.beginStruct();
3380 Elements.add(llvm::ConstantExpr::getIntToPtr(
3381 llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
3383 Elements.add(MakeConstantString(ProtocolName,
".objc_protocol_name"));
3384 Elements.add(ProtocolList);
3385 Elements.add(MethodList);
3386 Elements.add(MethodList);
3387 Elements.add(MethodList);
3388 Elements.add(MethodList);
3389 Elements.add(NULLPtr);
3390 Elements.add(NULLPtr);
3391 return Elements.finishAndCreateGlobal(SymbolForProtocol(ProtocolName),
3395void CGObjCGNU::GenerateProtocol(
const ObjCProtocolDecl *PD) {
3405 SmallVector<std::string, 16> Protocols;
3407 Protocols.push_back(PI->getNameAsString());
3408 SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
3409 SmallVector<const ObjCMethodDecl*, 16> OptionalInstanceMethods;
3411 if (I->isOptional())
3412 OptionalInstanceMethods.push_back(I);
3414 InstanceMethods.push_back(I);
3416 SmallVector<const ObjCMethodDecl*, 16> ClassMethods;
3417 SmallVector<const ObjCMethodDecl*, 16> OptionalClassMethods;
3419 if (I->isOptional())
3420 OptionalClassMethods.push_back(I);
3422 ClassMethods.push_back(I);
3424 llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
3425 llvm::Constant *InstanceMethodList =
3426 GenerateProtocolMethodList(InstanceMethods);
3427 llvm::Constant *ClassMethodList =
3428 GenerateProtocolMethodList(ClassMethods);
3429 llvm::Constant *OptionalInstanceMethodList =
3430 GenerateProtocolMethodList(OptionalInstanceMethods);
3431 llvm::Constant *OptionalClassMethodList =
3432 GenerateProtocolMethodList(OptionalClassMethods);
3440 llvm::Constant *PropertyList =
3441 GeneratePropertyList(
nullptr, PD,
false,
false);
3442 llvm::Constant *OptionalPropertyList =
3443 GeneratePropertyList(
nullptr, PD,
false,
true);
3449 ConstantInitBuilder Builder(CGM);
3450 auto Elements = Builder.beginStruct();
3452 llvm::ConstantExpr::getIntToPtr(
3453 llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
3454 Elements.add(MakeConstantString(ProtocolName));
3455 Elements.add(ProtocolList);
3456 Elements.add(InstanceMethodList);
3457 Elements.add(ClassMethodList);
3458 Elements.add(OptionalInstanceMethodList);
3459 Elements.add(OptionalClassMethodList);
3460 Elements.add(PropertyList);
3461 Elements.add(OptionalPropertyList);
3462 ExistingProtocols[ProtocolName] =
3463 Elements.finishAndCreateGlobal(
".objc_protocol", CGM.
getPointerAlign());
3465void CGObjCGNU::GenerateProtocolHolderCategory() {
3468 ConstantInitBuilder Builder(CGM);
3469 auto Elements = Builder.beginStruct();
3471 const std::string ClassName =
"__ObjC_Protocol_Holder_Ugly_Hack";
3472 const std::string CategoryName =
"AnotherHack";
3473 Elements.add(MakeConstantString(CategoryName));
3474 Elements.add(MakeConstantString(ClassName));
3476 Elements.add(GenerateMethodList(ClassName, CategoryName, {},
false));
3478 Elements.add(GenerateMethodList(ClassName, CategoryName, {},
true));
3481 ConstantInitBuilder ProtocolListBuilder(CGM);
3482 auto ProtocolList = ProtocolListBuilder.beginStruct();
3483 ProtocolList.add(NULLPtr);
3484 ProtocolList.addInt(LongTy, ExistingProtocols.size());
3485 auto ProtocolElements = ProtocolList.beginArray(PtrTy);
3486 for (
auto iter = ExistingProtocols.begin(), endIter = ExistingProtocols.end();
3487 iter != endIter ; iter++) {
3488 ProtocolElements.add(iter->getValue());
3490 ProtocolElements.finishAndAddTo(ProtocolList);
3491 Elements.add(ProtocolList.finishAndCreateGlobal(
".objc_protocol_list",
3493 Categories.push_back(
3508llvm::Constant *CGObjCGNU::MakeBitField(ArrayRef<bool> bits) {
3509 int bitCount = bits.size();
3511 if (bitCount < ptrBits) {
3513 for (
int i=0 ; i<bitCount ; ++i) {
3514 if (bits[i]) val |= 1ULL<<(i+1);
3516 return llvm::ConstantInt::get(IntPtrTy, val);
3518 SmallVector<llvm::Constant *, 8> values;
3520 while (v < bitCount) {
3522 for (
int i=0 ; (i<32) && (v<bitCount) ; ++i) {
3523 if (bits[v]) word |= 1<<i;
3526 values.push_back(llvm::ConstantInt::get(Int32Ty, word));
3529 ConstantInitBuilder builder(CGM);
3530 auto fields = builder.beginStruct();
3531 fields.addInt(Int32Ty, values.size());
3532 auto array = fields.beginArray();
3533 for (
auto *v : values) array.add(v);
3534 array.finishAndAddTo(fields);
3536 llvm::Constant *GS =
3538 llvm::Constant *ptr = llvm::ConstantExpr::getPtrToInt(GS, IntPtrTy);
3542llvm::Constant *CGObjCGNU::GenerateCategoryProtocolList(
const
3543 ObjCCategoryDecl *OCD) {
3545 const auto RuntimeProtos =
3546 GetRuntimeProtocolList(RefPro.begin(), RefPro.end());
3547 SmallVector<std::string, 16> Protocols;
3548 for (
const auto *PD : RuntimeProtos)
3550 return GenerateProtocolList(Protocols);
3553void CGObjCGNU::GenerateCategory(
const ObjCCategoryImplDecl *OCD) {
3555 std::string ClassName =
Class->getNameAsString();
3561 ConstantInitBuilder Builder(CGM);
3562 auto Elements = Builder.beginStruct();
3563 Elements.add(MakeConstantString(CategoryName));
3564 Elements.add(MakeConstantString(ClassName));
3566 SmallVector<ObjCMethodDecl*, 16> InstanceMethods;
3567 InstanceMethods.insert(InstanceMethods.begin(), OCD->
instmeth_begin(),
3570 GenerateMethodList(ClassName, CategoryName, InstanceMethods,
false));
3574 SmallVector<ObjCMethodDecl*, 16> ClassMethods;
3577 Elements.add(GenerateMethodList(ClassName, CategoryName, ClassMethods,
true));
3580 Elements.add(GenerateCategoryProtocolList(CatDecl));
3582 const ObjCCategoryDecl *Category =
3586 Elements.add(GeneratePropertyList(OCD, Category,
false));
3588 Elements.add(GeneratePropertyList(OCD, Category,
true));
3590 Elements.addNullPointer(PtrTy);
3591 Elements.addNullPointer(PtrTy);
3595 Categories.push_back(Elements.finishAndCreateGlobal(
3596 std::string(
".objc_category_") + ClassName + CategoryName,
3600llvm::Constant *CGObjCGNU::GeneratePropertyList(
const Decl *Container,
3601 const ObjCContainerDecl *OCD,
3602 bool isClassProperty,
3603 bool protocolOptionalProperties) {
3605 SmallVector<const ObjCPropertyDecl *, 16> Properties;
3606 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
3610 std::function<void(
const ObjCProtocolDecl *Proto)> collectProtocolProperties
3611 = [&](
const ObjCProtocolDecl *Proto) {
3612 for (
const auto *P : Proto->protocols())
3613 collectProtocolProperties(P);
3614 for (
const auto *PD : Proto->properties()) {
3615 if (isClassProperty != PD->isClassProperty())
3623 Properties.push_back(PD);
3627 if (
const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
3629 for (
auto *PD : ClassExt->properties()) {
3630 if (isClassProperty != PD->isClassProperty())
3633 Properties.push_back(PD);
3637 if (isClassProperty != PD->isClassProperty())
3641 if (isProtocol && (protocolOptionalProperties != PD->isOptional()))
3648 Properties.push_back(PD);
3651 if (
const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
3653 collectProtocolProperties(P);
3654 else if (
const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD))
3655 for (
const auto *P : CD->protocols())
3656 collectProtocolProperties(P);
3658 auto numProperties = Properties.size();
3660 if (numProperties == 0)
3663 ConstantInitBuilder builder(CGM);
3664 auto propertyList = builder.beginStruct();
3665 auto properties = PushPropertyListHeader(propertyList, numProperties);
3669 for (
auto *property : Properties) {
3670 bool isSynthesized =
false;
3671 bool isDynamic =
false;
3675 isSynthesized = (propertyImpl->getPropertyImplementation() ==
3677 isDynamic = (propertyImpl->getPropertyImplementation() ==
3681 PushProperty(properties, property, Container, isSynthesized, isDynamic);
3683 properties.finishAndAddTo(propertyList);
3685 return propertyList.finishAndCreateGlobal(
".objc_property_list",
3689void CGObjCGNU::RegisterAlias(
const ObjCCompatibleAliasDecl *OAD) {
3691 ObjCInterfaceDecl *ClassDecl =
3697void CGObjCGNU::GenerateClass(
const ObjCImplementationDecl *OID) {
3701 const ObjCInterfaceDecl * SuperClassDecl =
3703 std::string SuperClassName;
3704 if (SuperClassDecl) {
3706 EmitClassRef(SuperClassName);
3710 ObjCInterfaceDecl *ClassDecl =
3716 std::string classSymbolName =
"__objc_class_name_" + ClassName;
3717 if (
auto *symbol = TheModule.getGlobalVariable(classSymbolName)) {
3718 symbol->setInitializer(llvm::ConstantInt::get(LongTy, 0));
3720 new llvm::GlobalVariable(TheModule, LongTy,
false,
3721 llvm::GlobalValue::ExternalLinkage,
3722 llvm::ConstantInt::get(LongTy, 0),
3732 SmallVector<llvm::Constant*, 16> IvarNames;
3733 SmallVector<llvm::Constant*, 16> IvarTypes;
3734 SmallVector<llvm::Constant*, 16> IvarOffsets;
3735 SmallVector<llvm::Constant*, 16> IvarAligns;
3736 SmallVector<Qualifiers::ObjCLifetime, 16> IvarOwnership;
3738 ConstantInitBuilder IvarOffsetBuilder(CGM);
3739 auto IvarOffsetValues = IvarOffsetBuilder.beginArray(PtrToIntTy);
3740 SmallVector<bool, 16> WeakIvars;
3741 SmallVector<bool, 16> StrongIvars;
3743 int superInstanceSize = !SuperClassDecl ? 0 :
3748 instanceSize = 0 - (instanceSize - superInstanceSize);
3754 IvarNames.push_back(MakeConstantString(IVD->getNameAsString()));
3756 std::string TypeStr;
3758 IvarTypes.push_back(MakeConstantString(TypeStr));
3759 IvarAligns.push_back(llvm::ConstantInt::get(IntTy,
3762 uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
3765 Offset = BaseOffset - superInstanceSize;
3767 llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset);
3769 std::string OffsetName =
"__objc_ivar_offset_value_" + ClassName +
"." +
3770 IVD->getNameAsString();
3772 llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName);
3774 OffsetVar->setInitializer(OffsetValue);
3778 OffsetVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
3780 OffsetVar =
new llvm::GlobalVariable(TheModule, Int32Ty,
3781 false, llvm::GlobalValue::ExternalLinkage,
3782 OffsetValue, OffsetName);
3783 IvarOffsets.push_back(OffsetValue);
3784 IvarOffsetValues.add(OffsetVar);
3786 IvarOwnership.push_back(lt);
3789 StrongIvars.push_back(
true);
3790 WeakIvars.push_back(
false);
3793 StrongIvars.push_back(
false);
3794 WeakIvars.push_back(
true);
3797 StrongIvars.push_back(
false);
3798 WeakIvars.push_back(
false);
3801 llvm::Constant *StrongIvarBitmap = MakeBitField(StrongIvars);
3802 llvm::Constant *WeakIvarBitmap = MakeBitField(WeakIvars);
3803 llvm::GlobalVariable *IvarOffsetArray =
3804 IvarOffsetValues.finishAndCreateGlobal(
".ivar.offsets",
3808 SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
3809 InstanceMethods.insert(InstanceMethods.begin(), OID->
instmeth_begin(),
3812 SmallVector<const ObjCMethodDecl*, 16> ClassMethods;
3816 llvm::Constant *Properties = GeneratePropertyList(OID, ClassDecl);
3819 auto RefProtocols = ClassDecl->
protocols();
3820 auto RuntimeProtocols =
3821 GetRuntimeProtocolList(RefProtocols.begin(), RefProtocols.end());
3822 SmallVector<std::string, 16> Protocols;
3823 for (
const auto *I : RuntimeProtocols)
3824 Protocols.push_back(I->getNameAsString());
3827 llvm::Constant *SuperClass;
3828 if (!SuperClassName.empty()) {
3829 SuperClass = MakeConstantString(SuperClassName,
".super_class_name");
3831 SuperClass = llvm::ConstantPointerNull::get(PtrToInt8Ty);
3834 llvm::Constant *MethodList = GenerateMethodList(ClassName,
"",
3835 InstanceMethods,
false);
3836 llvm::Constant *ClassMethodList = GenerateMethodList(ClassName,
"",
3837 ClassMethods,
true);
3838 llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
3839 IvarOffsets, IvarAligns, IvarOwnership);
3850 llvm::Type *IndexTy = Int32Ty;
3851 llvm::Constant *offsetPointerIndexes[] = {Zeros[0],
3852 llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 2 : 1),
nullptr,
3853 llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 3 : 2) };
3855 unsigned ivarIndex = 0;
3858 const std::string Name = GetIVarOffsetVariableName(ClassDecl, IVD);
3859 offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, ivarIndex);
3861 llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr(
3863 offsetPointerIndexes);
3865 llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name);
3867 offset->setInitializer(offsetValue);
3871 offset->setLinkage(llvm::GlobalValue::ExternalLinkage);
3874 new llvm::GlobalVariable(TheModule, offsetValue->getType(),
3875 false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name);
3878 llvm::Constant *ZeroPtr = llvm::ConstantInt::get(IntPtrTy, 0);
3881 llvm::Constant *MetaClassStruct = GenerateClassStructure(
3882 NULLPtr, NULLPtr, 0x12L, ClassName.c_str(),
nullptr, Zeros[0],
3883 NULLPtr, ClassMethodList, NULLPtr, NULLPtr,
3884 GeneratePropertyList(OID, ClassDecl,
true), ZeroPtr, ZeroPtr,
true);
3889 llvm::Constant *ClassStruct = GenerateClassStructure(
3890 MetaClassStruct, SuperClass, 0x11L, ClassName.c_str(),
nullptr,
3891 llvm::ConstantInt::getSigned(LongTy, instanceSize), IvarList, MethodList,
3892 GenerateProtocolList(Protocols), IvarOffsetArray, Properties,
3893 StrongIvarBitmap, WeakIvarBitmap);
3898 if (ClassPtrAlias) {
3899 ClassPtrAlias->replaceAllUsesWith(ClassStruct);
3900 ClassPtrAlias->eraseFromParent();
3901 ClassPtrAlias =
nullptr;
3903 if (MetaClassPtrAlias) {
3904 MetaClassPtrAlias->replaceAllUsesWith(MetaClassStruct);
3905 MetaClassPtrAlias->eraseFromParent();
3906 MetaClassPtrAlias =
nullptr;
3910 Classes.push_back(ClassStruct);
3913llvm::Function *CGObjCGNU::ModuleInitFunction() {
3915 if (Classes.empty() && Categories.empty() && ConstantStrings.empty() &&
3916 ExistingProtocols.empty() && SelectorTable.empty())
3920 GenerateProtocolHolderCategory();
3922 llvm::StructType *selStructTy = dyn_cast<llvm::StructType>(SelectorElemTy);
3925 { PtrToInt8Ty, PtrToInt8Ty });
3929 llvm::Constant *statics = NULLPtr;
3930 if (!ConstantStrings.empty()) {
3931 llvm::GlobalVariable *fileStatics = [&] {
3932 ConstantInitBuilder builder(CGM);
3933 auto staticsStruct = builder.beginStruct();
3936 if (stringClass.empty()) stringClass =
"NXConstantString";
3937 staticsStruct.add(MakeConstantString(stringClass,
3938 ".objc_static_class_name"));
3940 auto array = staticsStruct.beginArray();
3941 array.addAll(ConstantStrings);
3943 array.finishAndAddTo(staticsStruct);
3945 return staticsStruct.finishAndCreateGlobal(
".objc_statics",
3949 ConstantInitBuilder builder(CGM);
3950 auto allStaticsArray = builder.beginArray(fileStatics->getType());
3951 allStaticsArray.add(fileStatics);
3952 allStaticsArray.addNullPointer(fileStatics->getType());
3954 statics = allStaticsArray.finishAndCreateGlobal(
".objc_statics_ptr",
3960 SmallVector<llvm::GlobalAlias*, 16> selectorAliases;
3961 unsigned selectorCount;
3964 llvm::GlobalVariable *selectorList = [&] {
3965 ConstantInitBuilder builder(CGM);
3966 auto selectors = builder.beginArray(selStructTy);
3967 auto &table = SelectorTable;
3968 std::vector<Selector> allSelectors;
3969 for (
auto &entry : table)
3970 allSelectors.push_back(entry.first);
3971 llvm::sort(allSelectors);
3973 for (
auto &untypedSel : allSelectors) {
3974 std::string selNameStr = untypedSel.getAsString();
3975 llvm::Constant *selName = ExportUniqueString(selNameStr,
".objc_sel_name");
3977 for (TypedSelector &sel : table[untypedSel]) {
3978 llvm::Constant *selectorTypeEncoding = NULLPtr;
3979 if (!sel.first.empty())
3980 selectorTypeEncoding =
3981 MakeConstantString(sel.first,
".objc_sel_types");
3983 auto selStruct = selectors.beginStruct(selStructTy);
3984 selStruct.add(selName);
3985 selStruct.add(selectorTypeEncoding);
3986 selStruct.finishAndAddTo(selectors);
3989 selectorAliases.push_back(sel.second);
3994 selectorCount = selectors.size();
4000 auto selStruct = selectors.beginStruct(selStructTy);
4001 selStruct.add(NULLPtr);
4002 selStruct.add(NULLPtr);
4003 selStruct.finishAndAddTo(selectors);
4005 return selectors.finishAndCreateGlobal(
".objc_selector_list",
4010 for (
unsigned i = 0; i < selectorCount; ++i) {
4011 llvm::Constant *idxs[] = {
4013 llvm::ConstantInt::get(Int32Ty, i)
4016 llvm::Constant *selPtr = llvm::ConstantExpr::getGetElementPtr(
4017 selectorList->getValueType(), selectorList, idxs);
4018 selectorAliases[i]->replaceAllUsesWith(selPtr);
4019 selectorAliases[i]->eraseFromParent();
4022 llvm::GlobalVariable *symtab = [&] {
4023 ConstantInitBuilder builder(CGM);
4024 auto symtab = builder.beginStruct();
4027 symtab.addInt(LongTy, selectorCount);
4029 symtab.add(selectorList);
4032 symtab.addInt(CGM.
Int16Ty, Classes.size());
4034 symtab.addInt(CGM.
Int16Ty, Categories.size());
4037 auto classList = symtab.beginArray(PtrToInt8Ty);
4038 classList.addAll(Classes);
4039 classList.addAll(Categories);
4041 classList.add(statics);
4042 classList.add(NULLPtr);
4043 classList.finishAndAddTo(symtab);
4051 llvm::Constant *module = [&] {
4052 llvm::Type *moduleEltTys[] = {
4053 LongTy, LongTy, PtrToInt8Ty, symtab->getType(), IntTy
4055 llvm::StructType *moduleTy = llvm::StructType::get(
4057 ArrayRef(moduleEltTys).drop_back(
unsigned(RuntimeVersion < 10)));
4059 ConstantInitBuilder builder(CGM);
4060 auto module = builder.beginStruct(moduleTy);
4062 module.addInt(LongTy, RuntimeVersion);
4064 module.addInt(LongTy, CGM.getDataLayout().getTypeStoreSize(moduleTy));
4071 module.add(MakeConstantString(path, ".objc_source_file_name"));
4074 if (RuntimeVersion >= 10) {
4076 case LangOptions::GCOnly:
4077 module.addInt(IntTy, 2);
4079 case LangOptions::NonGC:
4081 module.addInt(IntTy, 1);
4083 module.addInt(IntTy, 0);
4085 case LangOptions::HybridGC:
4086 module.addInt(IntTy, 1);
4091 return module.finishAndCreateGlobal("", CGM.getPointerAlign());
4096 llvm::Function * LoadFunction = llvm::Function::Create(
4097 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
false),
4098 llvm::GlobalValue::InternalLinkage,
".objc_load_function",
4100 llvm::BasicBlock *EntryBB =
4101 llvm::BasicBlock::Create(VMContext,
"entry", LoadFunction);
4102 CGBuilderTy Builder(CGM, VMContext);
4103 Builder.SetInsertPoint(EntryBB);
4105 llvm::FunctionType *FT =
4106 llvm::FunctionType::get(Builder.getVoidTy(), module->getType(),
true);
4107 llvm::FunctionCallee Register =
4109 Builder.CreateCall(Register, module);
4111 if (!ClassAliases.empty()) {
4112 llvm::Type *ArgTypes[2] = {PtrTy, PtrToInt8Ty};
4113 llvm::FunctionType *RegisterAliasTy =
4114 llvm::FunctionType::get(Builder.getVoidTy(),
4116 llvm::Function *RegisterAlias = llvm::Function::Create(
4118 llvm::GlobalValue::ExternalWeakLinkage,
"class_registerAlias_np",
4120 llvm::BasicBlock *AliasBB =
4121 llvm::BasicBlock::Create(VMContext,
"alias", LoadFunction);
4122 llvm::BasicBlock *NoAliasBB =
4123 llvm::BasicBlock::Create(VMContext,
"no_alias", LoadFunction);
4126 llvm::Value *HasRegisterAlias = Builder.CreateICmpNE(RegisterAlias,
4127 llvm::Constant::getNullValue(RegisterAlias->getType()));
4128 Builder.CreateCondBr(HasRegisterAlias, AliasBB, NoAliasBB);
4131 Builder.SetInsertPoint(AliasBB);
4133 for (std::vector<ClassAliasPair>::iterator iter = ClassAliases.begin();
4134 iter != ClassAliases.end(); ++iter) {
4135 llvm::Constant *TheClass =
4136 TheModule.getGlobalVariable(
"_OBJC_CLASS_" + iter->first,
true);
4138 Builder.CreateCall(RegisterAlias,
4139 {TheClass, MakeConstantString(iter->second)});
4143 Builder.CreateBr(NoAliasBB);
4146 Builder.SetInsertPoint(NoAliasBB);
4148 Builder.CreateRetVoid();
4150 return LoadFunction;
4153llvm::Function *CGObjCGNU::GenerateMethod(
const ObjCMethodDecl *OMD,
4154 const ObjCContainerDecl *CD) {
4155 CodeGenTypes &Types = CGM.
getTypes();
4156 llvm::FunctionType *MethodTy =
4160 std::string FunctionName =
4161 getSymbolNameForMethod(OMD, !isDirect);
4164 return llvm::Function::Create(MethodTy,
4165 llvm::GlobalVariable::InternalLinkage,
4166 FunctionName, &TheModule);
4169 auto I = DirectMethodDefinitions.find(COMD);
4170 llvm::Function *OldFn =
nullptr, *
Fn =
nullptr;
4172 if (I == DirectMethodDefinitions.end()) {
4174 llvm::Function::Create(MethodTy, llvm::GlobalVariable::ExternalLinkage,
4175 FunctionName, &TheModule);
4176 DirectMethodDefinitions.insert(std::make_pair(COMD, F));
4193 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
"",
4195 Fn->takeName(OldFn);
4196 OldFn->replaceAllUsesWith(Fn);
4197 OldFn->eraseFromParent();
4204void CGObjCGNU::GenerateDirectMethodsPreconditionCheck(
4205 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
4206 const ObjCContainerDecl *CD) {
4208 "Direct method precondition checks not supported in GNU runtime yet");
4211void CGObjCGNU::GenerateDirectMethodPrologue(CodeGenFunction &CGF,
4213 const ObjCMethodDecl *OMD,
4214 const ObjCContainerDecl *CD) {
4216 "Direct method precondition checks not supported in GNU runtime yet");
4219llvm::FunctionCallee CGObjCGNU::GetPropertyGetFunction() {
4220 return GetPropertyFn;
4223llvm::FunctionCallee CGObjCGNU::GetPropertySetFunction() {
4224 return SetPropertyFn;
4227llvm::FunctionCallee CGObjCGNU::GetOptimizedPropertySetFunction(
bool atomic,
4232llvm::FunctionCallee CGObjCGNU::GetGetStructFunction() {
4233 return GetStructPropertyFn;
4236llvm::FunctionCallee CGObjCGNU::GetSetStructFunction() {
4237 return SetStructPropertyFn;
4240llvm::FunctionCallee CGObjCGNU::GetCppAtomicObjectGetFunction() {
4244llvm::FunctionCallee CGObjCGNU::GetCppAtomicObjectSetFunction() {
4248llvm::FunctionCallee CGObjCGNU::EnumerationMutationFunction() {
4249 return EnumerationMutationFn;
4252void CGObjCGNU::EmitSynchronizedStmt(CodeGenFunction &CGF,
4253 const ObjCAtSynchronizedStmt &S) {
4254 EmitAtSynchronizedStmt(CGF, S, SyncEnterFn, SyncExitFn);
4258void CGObjCGNU::EmitTryStmt(CodeGenFunction &CGF,
4259 const ObjCAtTryStmt &S) {
4271 EmitTryCatchStmt(CGF, S, EnterCatchFn, ExitCatchFn, ExceptionReThrowFn);
4274void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
4275 const ObjCAtThrowStmt &S,
4276 bool ClearInsertionPoint) {
4277 llvm::Value *ExceptionAsObject;
4278 bool isRethrow =
false;
4282 ExceptionAsObject = Exception;
4285 "Unexpected rethrow outside @catch block.");
4289 if (isRethrow && (usesSEHExceptions || usesCxxExceptions)) {
4298 Throw->setDoesNotReturn();
4300 ExceptionAsObject = CGF.
Builder.CreateBitCast(ExceptionAsObject, IdTy);
4301 llvm::CallBase *Throw =
4303 Throw->setDoesNotReturn();
4305 CGF.
Builder.CreateUnreachable();
4306 if (ClearInsertionPoint)
4307 CGF.
Builder.ClearInsertionPoint();
4310llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGenFunction &CGF,
4311 Address AddrWeakObj) {
4313 return B.CreateCall(
4314 WeakReadFn, EnforceType(B, AddrWeakObj.
emitRawPointer(CGF), PtrToIdTy));
4317void CGObjCGNU::EmitObjCWeakAssign(CodeGenFunction &CGF,
4318 llvm::Value *src, Address dst) {
4320 src = EnforceType(B, src, IdTy);
4321 llvm::Value *dstVal = EnforceType(B,
dst.emitRawPointer(CGF), PtrToIdTy);
4322 B.CreateCall(WeakAssignFn, {src, dstVal});
4325void CGObjCGNU::EmitObjCGlobalAssign(CodeGenFunction &CGF,
4326 llvm::Value *src, Address dst,
4329 src = EnforceType(B, src, IdTy);
4330 llvm::Value *dstVal = EnforceType(B,
dst.emitRawPointer(CGF), PtrToIdTy);
4332 assert(!threadlocal &&
"EmitObjCGlobalAssign - Threal Local API NYI");
4333 B.CreateCall(GlobalAssignFn, {src, dstVal});
4336void CGObjCGNU::EmitObjCIvarAssign(CodeGenFunction &CGF,
4337 llvm::Value *src, Address dst,
4338 llvm::Value *ivarOffset) {
4340 src = EnforceType(B, src, IdTy);
4341 llvm::Value *dstVal = EnforceType(B,
dst.emitRawPointer(CGF), IdTy);
4342 B.CreateCall(IvarAssignFn, {src, dstVal, ivarOffset});
4345void CGObjCGNU::EmitObjCStrongCastAssign(CodeGenFunction &CGF,
4346 llvm::Value *src, Address dst) {
4348 src = EnforceType(B, src, IdTy);
4349 llvm::Value *dstVal = EnforceType(B,
dst.emitRawPointer(CGF), PtrToIdTy);
4350 B.CreateCall(StrongCastAssignFn, {src, dstVal});
4353void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF,
4356 llvm::Value *Size) {
4358 llvm::Value *DestPtrVal = EnforceType(B, DestPtr.
emitRawPointer(CGF), PtrTy);
4359 llvm::Value *SrcPtrVal = EnforceType(B, SrcPtr.
emitRawPointer(CGF), PtrTy);
4361 B.CreateCall(MemMoveFn, {DestPtrVal, SrcPtrVal,
Size});
4364llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable(
4365 const ObjCInterfaceDecl *ID,
4366 const ObjCIvarDecl *Ivar) {
4367 const std::string Name = GetIVarOffsetVariableName(ID, Ivar);
4371 llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
4372 if (!IvarOffsetPointer)
4373 IvarOffsetPointer =
new llvm::GlobalVariable(
4374 TheModule, llvm::PointerType::getUnqual(VMContext),
false,
4375 llvm::GlobalValue::ExternalLinkage,
nullptr, Name);
4376 return IvarOffsetPointer;
4379LValue CGObjCGNU::EmitObjCValueForIvar(CodeGenFunction &CGF,
4381 llvm::Value *BaseValue,
4382 const ObjCIvarDecl *Ivar,
4383 unsigned CVRQualifiers) {
4384 const ObjCInterfaceDecl *
ID =
4385 ObjectTy->
castAs<ObjCObjectType>()->getInterface();
4386 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4387 EmitIvarOffset(CGF, ID, Ivar));
4406llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF,
4408 const ObjCIvarDecl *Ivar) {
4415 if (RuntimeVersion < 10 ||
4417 return CGF.
Builder.CreateZExtOrBitCast(
4421 llvm::PointerType::getUnqual(VMContext),
4422 ObjCIvarOffsetVariable(
Interface, Ivar),
4426 std::string
name =
"__objc_ivar_offset_value_" +
4429 llvm::Value *Offset = TheModule.getGlobalVariable(name);
4431 auto GV =
new llvm::GlobalVariable(TheModule, IntTy,
4432 false, llvm::GlobalValue::LinkOnceAnyLinkage,
4433 llvm::Constant::getNullValue(IntTy), name);
4438 if (Offset->getType() != PtrDiffTy)
4439 Offset = CGF.
Builder.CreateZExtOrBitCast(Offset, PtrDiffTy);
4443 return llvm::ConstantInt::get(PtrDiffTy, Offset,
true);
4449 switch (Runtime.getKind()) {
4451 if (Runtime.getVersion() >= VersionTuple(2, 0))
4452 return new CGObjCGNUstep2(CGM);
4453 return new CGObjCGNUstep(CGM);
4456 return new CGObjCGCC(CGM);
4459 return new CGObjCObjFW(CGM);
4465 llvm_unreachable(
"these runtimes are not GNU runtimes");
4467 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])
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Defines the SourceManager interface.
Defines the Objective-C statement AST node classes.
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
void getObjCEncodingForType(QualType T, std::string &S, const FieldDecl *Field=nullptr, QualType *NotEncodedT=nullptr) const
Emit the Objective-CC type encoding for the given type T into S.
std::string getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, bool Extended=false) const
Emit the encoded type for the method declaration Decl into S.
std::string getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, const Decl *Container) const
getObjCEncodingForPropertyDecl - Return the encoded type for this method declaration.
const ASTRecordLayout & getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const
Get or compute information about the layout of the specified Objective-C interface.
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
ObjCPropertyImplDecl * getObjCPropertyImplDeclForPropertyDecl(const ObjCPropertyDecl *PD, const Decl *Container) const
QualType getObjCSelType() const
Retrieve the type that corresponds to the predefined Objective-C 'SEL' type.
QualType getObjCIdType() const
Represents the Objective-CC id type.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
void getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT, QualType T, std::string &S, bool Extended) const
getObjCEncodingForMethodParameter - Return the encoded type for a single method parameter or return t...
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
uint64_t getCharWidth() const
Return the size of the character type, in bits.
CharUnits getSize() const
getSize - Get the record size in characters.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::LoadInst * CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, CharUnits Align, const llvm::Twine &Name="")
virtual llvm::Constant * getAddrOfRTTIDescriptor(QualType Ty)=0
virtual CatchTypeInfo getCatchAllTypeInfo()
Implements runtime-specific code generation functions.
void add(RValue rvalue, QualType type)
void addFrom(const CallArgList &other)
Add all the arguments from another CallArgList to this one.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
llvm::CallBase * EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args, const Twine &name="")
Emits a call or invoke instruction to the given runtime function.
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
llvm::Value * EmitObjCThrowOperand(const Expr *expr)
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
JumpDest ReturnBlock
ReturnBlock - Unified return block.
llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)
CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
llvm::Value * LoadObjCSelf()
LoadObjCSelf - Load the value of self.
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
SmallVector< llvm::Value *, 8 > ObjCEHValueStack
ObjCEHValueStack - Stack of Objective-C exception values, used for rethrows.
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
static bool hasAggregateEvaluationKind(QualType T)
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
llvm::LLVMContext & getLLVMContext()
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
This class organizes the cross-function state that is used while generating LLVM code.
void setGVProperties(llvm::GlobalValue *GV, GlobalDecl GD) const
Set visibility, dllimport/dllexport and dso_local.
llvm::Module & getModule() const
llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)
Create or return a runtime function declaration with the specified type and name.
void addCompilerUsedGlobal(llvm::GlobalValue *GV)
Add a global to a list to be added to the llvm.compiler.used metadata.
bool ReturnTypeUsesFPRet(QualType ResultType)
Return true iff the given type uses 'fpret' when used as a return type.
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const TargetInfo & getTarget() const
void addUsedGlobal(llvm::GlobalValue *GV)
Add a global to a list to be added to the llvm.used metadata.
const llvm::DataLayout & getDataLayout() const
CGCXXABI & getCXXABI() const
const llvm::Triple & getTriple() const
bool ReturnTypeHasInReg(const CGFunctionInfo &FI)
Return true iff the given type has inreg set.
ASTContext & getContext() const
bool ReturnTypeUsesSRet(const CGFunctionInfo &FI)
Return true iff the given type uses 'sret' when used as a return type.
const CodeGenOptions & getCodeGenOpts() const
llvm::LLVMContext & getLLVMContext()
llvm::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
ConstantAddress GetAddrOfConstantCString(const std::string &Str, StringRef GlobalName=".str")
Returns a pointer to a character array containing the literal and a terminating '\0' character.
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
const CGFunctionInfo & arrangeObjCMethodDeclaration(const ObjCMethodDecl *MD)
Objective-C methods are C functions with some implicit parameters.
bool isZeroInitializable(QualType T)
IsZeroInitializable - Return whether a type can be zero-initialized (in the C++ sense) with an LLVM z...
void add(llvm::Constant *value)
Add a new value to this initializer.
void addInt(llvm::IntegerType *intTy, uint64_t value, bool isSigned=false)
Add an integer value of a specific type.
void addNullPointer(llvm::PointerType *ptrTy)
Add a null pointer of a specific type.
ArrayBuilder beginArray(llvm::Type *eltTy=nullptr)
llvm::GlobalVariable * finishAndCreateGlobal(As &&...args)
Given that this builder was created by beginning an array or struct directly on a ConstantInitBuilder...
StructBuilder beginStruct(llvm::StructType *ty=nullptr)
void finishAndAddTo(AggregateBuilderBase &parent)
Given that this builder was created by beginning an array or struct component on the given parent bui...
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
Address getAggregateAddress() const
getAggregateAddr() - Return the Value* of the address of the aggregate.
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
llvm::Value * getPointer() const
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
bool isWeakImported() const
Determine whether this is a weak-imported symbol.
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
StringRef getName() const
The name of this FileEntry.
DirectoryEntryRef getDir() const
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
clang::ObjCRuntime ObjCRuntime
std::string ObjCConstantStringClass
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Visibility getVisibility() const
Determines the visibility of this entity.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
const Expr * getThrowExpr() const
const ObjCProtocolList & getReferencedProtocols() const
ObjCCategoryDecl * getCategoryDecl() const
const ObjCInterfaceDecl * getClassInterface() const
classmeth_iterator classmeth_end() const
classmeth_iterator classmeth_begin() const
instmeth_range instance_methods() const
instmeth_iterator instmeth_end() const
instmeth_iterator instmeth_begin() const
prop_range properties() const
classmeth_range class_methods() const
propimpl_range property_impls() const
const ObjCInterfaceDecl * getClassInterface() const
Represents an ObjC class declaration.
all_protocol_iterator all_referenced_protocol_end() const
all_protocol_range all_referenced_protocols() const
ObjCIvarDecl * all_declared_ivar_begin()
all_declared_ivar_begin - return first ivar declared in this class, its extensions and its implementa...
protocol_range protocols() const
all_protocol_iterator all_referenced_protocol_begin() const
ObjCInterfaceDecl * getSuperClass() const
ObjCInterfaceDecl * getDefinition()
Retrieve the definition of this class, or NULL if this class has been forward-declared (with @class) ...
known_extensions_range known_extensions() const
ObjCInterfaceDecl * getDecl() const
Get the declaration of this interface.
ObjCIvarDecl - Represents an ObjC instance variable.
AccessControl getAccessControl() const
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
ObjCIvarDecl * getNextIvar()
ImplicitParamDecl * getSelfDecl() const
Stmt * getBody() const override
Retrieve the body of this method, if it has one.
ObjCMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
bool isDirectMethod() const
True if the method is tagged as objc_direct.
Selector getSelector() const
ImplicitParamDecl * getCmdDecl() const
QualType getReturnType() const
bool isClassMethod() const
const ObjCObjectType * getObjectType() const
Gets the type pointed to by this ObjC pointer.
const ObjCInterfaceType * getInterfaceType() const
If this pointer points to an Objective C @interface type, gets the type for that interface.
ObjCMethodDecl * getGetterMethodDecl() const
ObjCMethodDecl * getSetterMethodDecl() const
ObjCProtocolDecl * getDefinition()
Retrieve the definition of this protocol, if any.
bool isNonRuntimeProtocol() const
This is true iff the protocol is tagged with the objc_non_runtime_protocol attribute.
protocol_iterator protocol_begin() const
protocol_range protocols() const
protocol_iterator protocol_end() const
const VersionTuple & getVersion() const
bool isNonFragile() const
Does this runtime follow the set of implied behaviors for a "non-fragile" ABI?
Kind
The basic Objective-C runtimes that we know about.
@ MacOSX
'macosx' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the non-fragile AB...
@ FragileMacOSX
'macosx-fragile' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the fragil...
@ GNUstep
'gnustep' is the modern non-fragile GNUstep runtime.
@ ObjFW
'objfw' is the Objective-C runtime included in ObjFW
@ iOS
'ios' is the Apple-provided NeXT-derived runtime on iOS or the iOS simulator; it is always non-fragil...
@ GCC
'gcc' is the Objective-C runtime shipped with GCC, implementing a fragile Objective-C ABI
@ WatchOS
'watchos' is a variant of iOS for Apple's watchOS.
A (possibly-)qualified type.
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
@ OCL_None
There is no lifetime qualification on this type.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
std::string getAsString() const
Derive the full selector name (e.g.
bool containsNonAscii() const
unsigned getLength() const
uint32_t getCodeUnit(size_t i) const
StringRef getString() const
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
static DeclContext * castToDeclContext(const TranslationUnitDecl *D)
const T * castAs() const
Member-template castAs<specific type>.
bool isObjCQualifiedIdType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isObjCIdType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool hasPointerRepresentation() const
Whether this type is represented natively as a pointer.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
CGObjCRuntime * CreateGNUObjCRuntime(CodeGenModule &CGM)
Creates an instance of an Objective-C runtime class.
StringRef getName(const HeaderType T)
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
CustomizableOptional< FileEntryRef > OptionalFileEntryRef
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Result
The result type of a method or function.
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.
const half4 dst(half4 Src0, half4 Src1)
int const char * function
CharUnits getIntAlign() const
llvm::IntegerType * Int16Ty
llvm::PointerType * Int8PtrTy
CharUnits getPointerAlign() const