31#include "llvm/ADT/SmallVector.h"
32#include "llvm/ADT/StringMap.h"
33#include "llvm/IR/DataLayout.h"
34#include "llvm/IR/Intrinsics.h"
35#include "llvm/IR/LLVMContext.h"
36#include "llvm/IR/Module.h"
37#include "llvm/Support/Compiler.h"
38#include "llvm/Support/ConvertUTF.h"
49class LazyRuntimeFunction {
50 CodeGenModule *CGM =
nullptr;
51 llvm::FunctionType *FTy =
nullptr;
52 const char *FunctionName =
nullptr;
53 llvm::FunctionCallee Function =
nullptr;
56 LazyRuntimeFunction() =
default;
60 template <
typename... Tys>
61 void init(CodeGenModule *Mod,
const char *name, llvm::Type *RetTy,
67 SmallVector<llvm::Type *, 8> ArgTys({Types...});
68 FTy = llvm::FunctionType::get(RetTy, ArgTys,
false);
71 FTy = llvm::FunctionType::get(RetTy, {},
false);
75 llvm::FunctionType *
getType() {
return FTy; }
79 operator llvm::FunctionCallee() {
83 Function = CGM->CreateRuntimeFunction(FTy, FunctionName);
96 llvm::Module &TheModule;
99 llvm::StructType *ObjCSuperTy;
102 llvm::PointerType *PtrToObjCSuperTy;
106 llvm::PointerType *SelectorTy;
108 llvm::Type *SelectorElemTy;
111 llvm::IntegerType *Int8Ty;
114 llvm::PointerType *PtrToInt8Ty;
116 llvm::StructType *ProtocolTy;
118 llvm::PointerType *ProtocolPtrTy;
124 llvm::PointerType *IMPTy;
129 llvm::PointerType *IdTy;
131 llvm::Type *IdElemTy;
134 llvm::PointerType *PtrToIdTy;
139 llvm::IntegerType *IntTy;
143 llvm::PointerType *PtrTy;
147 llvm::IntegerType *LongTy;
149 llvm::IntegerType *SizeTy;
151 llvm::IntegerType *IntPtrTy;
153 llvm::IntegerType *PtrDiffTy;
156 llvm::PointerType *PtrToIntTy;
160 llvm::IntegerType *Int32Ty;
162 llvm::IntegerType *Int64Ty;
164 llvm::StructType *PropertyMetadataTy;
168 unsigned msgSendMDKind;
171 bool usesSEHExceptions;
173 bool usesCxxExceptions;
178 return (
R.getKind() ==
kind) &&
179 (
R.getVersion() >= VersionTuple(major, minor));
182 std::string ManglePublicSymbol(StringRef Name) {
183 return (StringRef(CGM.
getTriple().isOSBinFormatCOFF() ?
"$_" :
"._") + Name).str();
186 std::string SymbolForProtocol(Twine Name) {
187 return (ManglePublicSymbol(
"OBJC_PROTOCOL_") + Name).str();
190 std::string SymbolForProtocolRef(StringRef Name) {
191 return (ManglePublicSymbol(
"OBJC_REF_PROTOCOL_") + Name).str();
198 llvm::Constant *MakeConstantString(StringRef Str, StringRef Name =
"") {
199 ConstantAddress
Array =
208 llvm::Constant *ExportUniqueString(
const std::string &Str,
209 const std::string &prefix,
211 std::string
name = prefix + Str;
212 auto *ConstStr = TheModule.getGlobalVariable(name);
214 llvm::Constant *value = llvm::ConstantDataArray::getString(VMContext,Str);
215 auto *GV =
new llvm::GlobalVariable(TheModule, value->getType(),
true,
216 llvm::GlobalValue::LinkOnceODRLinkage, value, name);
217 GV->setComdat(TheModule.getOrInsertComdat(name));
219 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
226 llvm::Constant *MakePropertyEncodingString(
const ObjCPropertyDecl *PD,
227 const Decl *Container) {
230 std::string NameAndAttributes;
231 std::string TypeStr =
233 NameAndAttributes +=
'\0';
234 NameAndAttributes += TypeStr.length() + 3;
235 NameAndAttributes += TypeStr;
236 NameAndAttributes +=
'\0';
238 return MakeConstantString(NameAndAttributes);
244 void PushPropertyAttributes(ConstantStructBuilder &Fields,
245 const ObjCPropertyDecl *property,
bool isSynthesized=
true,
bool
247 int attrs =
property->getPropertyAttributes();
250 attrs &= ~ObjCPropertyAttribute::kind_copy;
251 attrs &= ~ObjCPropertyAttribute::kind_retain;
252 attrs &= ~ObjCPropertyAttribute::kind_weak;
253 attrs &= ~ObjCPropertyAttribute::kind_strong;
256 Fields.
addInt(Int8Ty, attrs & 0xff);
262 attrs |= isSynthesized ? (1<<0) : 0;
263 attrs |= isDynamic ? (1<<1) : 0;
266 Fields.
addInt(Int8Ty, attrs & 0xff);
272 virtual llvm::Constant *GenerateCategoryProtocolList(
const
273 ObjCCategoryDecl *OCD);
274 virtual ConstantArrayBuilder PushPropertyListHeader(ConstantStructBuilder &Fields,
277 Fields.
addInt(IntTy, count);
280 const llvm::DataLayout &DL = TheModule.getDataLayout();
281 Fields.
addInt(IntTy, DL.getTypeSizeInBits(PropertyMetadataTy) /
289 virtual void PushProperty(ConstantArrayBuilder &PropertiesArray,
290 const ObjCPropertyDecl *property,
292 bool isSynthesized=
true,
bool
294 auto Fields = PropertiesArray.
beginStruct(PropertyMetadataTy);
296 Fields.
add(MakePropertyEncodingString(property, OCD));
297 PushPropertyAttributes(Fields, property, isSynthesized, isDynamic);
298 auto addPropertyMethod = [&](
const ObjCMethodDecl *accessor) {
301 llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
302 Fields.
add(MakeConstantString(accessor->getSelector().getAsString()));
303 Fields.
add(TypeEncoding);
317 llvm::Value *EnforceType(CGBuilderTy &B, llvm::Value *
V, llvm::Type *Ty) {
318 if (
V->getType() == Ty)
320 return B.CreateBitCast(
V, Ty);
324 llvm::Constant *Zeros[2];
326 llvm::Constant *NULLPtr;
328 llvm::LLVMContext &VMContext;
336 llvm::GlobalAlias *ClassPtrAlias;
341 llvm::GlobalAlias *MetaClassPtrAlias;
343 std::vector<llvm::Constant*> Classes;
345 std::vector<llvm::Constant*> Categories;
348 std::vector<llvm::Constant*> ConstantStrings;
352 llvm::StringMap<llvm::Constant*> ObjCStrings;
354 llvm::StringMap<llvm::Constant*> ExistingProtocols;
360 typedef std::pair<std::string, llvm::GlobalAlias*> TypedSelector;
364 typedef llvm::DenseMap<Selector, SmallVector<TypedSelector, 2> >
368 SelectorMap SelectorTable;
372 Selector RetainSel, ReleaseSel, AutoreleaseSel;
376 LazyRuntimeFunction IvarAssignFn, StrongCastAssignFn, MemMoveFn, WeakReadFn,
377 WeakAssignFn, GlobalAssignFn;
379 typedef std::pair<std::string, std::string> ClassAliasPair;
381 std::vector<ClassAliasPair> ClassAliases;
385 LazyRuntimeFunction ExceptionThrowFn;
388 LazyRuntimeFunction ExceptionReThrowFn;
391 LazyRuntimeFunction EnterCatchFn;
394 LazyRuntimeFunction ExitCatchFn;
396 LazyRuntimeFunction SyncEnterFn;
398 LazyRuntimeFunction SyncExitFn;
403 LazyRuntimeFunction EnumerationMutationFn;
406 LazyRuntimeFunction GetPropertyFn;
409 LazyRuntimeFunction SetPropertyFn;
411 LazyRuntimeFunction GetStructPropertyFn;
413 LazyRuntimeFunction SetStructPropertyFn;
425 const int ProtocolVersion;
428 const int ClassABIVersion;
433 virtual llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
434 ArrayRef<llvm::Constant *> IvarTypes,
435 ArrayRef<llvm::Constant *> IvarOffsets,
436 ArrayRef<llvm::Constant *> IvarAlign,
437 ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership);
444 llvm::Constant *GenerateMethodList(StringRef ClassName,
445 StringRef CategoryName,
446 ArrayRef<const ObjCMethodDecl*> Methods,
447 bool isClassMethodList);
452 virtual llvm::Constant *GenerateEmptyProtocol(StringRef ProtocolName);
456 llvm::Constant *GeneratePropertyList(
const Decl *Container,
457 const ObjCContainerDecl *OCD,
458 bool isClassProperty=
false,
459 bool protocolOptionalProperties=
false);
463 llvm::Constant *GenerateProtocolList(ArrayRef<std::string> Protocols);
469 void GenerateProtocolHolderCategory();
472 llvm::Constant *GenerateClassStructure(
473 llvm::Constant *MetaClass,
474 llvm::Constant *SuperClass,
477 llvm::Constant *Version,
478 llvm::Constant *InstanceSize,
479 llvm::Constant *IVars,
480 llvm::Constant *Methods,
481 llvm::Constant *Protocols,
482 llvm::Constant *IvarOffsets,
483 llvm::Constant *Properties,
484 llvm::Constant *StrongIvarBitmap,
485 llvm::Constant *WeakIvarBitmap,
490 virtual llvm::Constant *GenerateProtocolMethodList(
491 ArrayRef<const ObjCMethodDecl*> Methods);
494 void EmitProtocolMethodList(
T &&Methods, llvm::Constant *&
Required,
496 SmallVector<const ObjCMethodDecl*, 16> RequiredMethods;
497 SmallVector<const ObjCMethodDecl*, 16> OptionalMethods;
498 for (
const auto *I : Methods)
500 OptionalMethods.push_back(I);
502 RequiredMethods.push_back(I);
503 Required = GenerateProtocolMethodList(RequiredMethods);
504 Optional = GenerateProtocolMethodList(OptionalMethods);
509 virtual llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
510 const std::string &TypeEncoding);
515 virtual std::string GetIVarOffsetVariableName(
const ObjCInterfaceDecl *ID,
516 const ObjCIvarDecl *Ivar) {
517 const std::string Name =
"__objc_ivar_offset_" +
ID->getNameAsString()
522 llvm::GlobalVariable *ObjCIvarOffsetVariable(
const ObjCInterfaceDecl *ID,
523 const ObjCIvarDecl *Ivar);
526 void EmitClassRef(
const std::string &className);
529 virtual llvm::Value *GetClassNamed(CodeGenFunction &CGF,
530 const std::string &Name,
bool isWeak);
535 virtual llvm::Value *LookupIMP(CodeGenFunction &CGF,
536 llvm::Value *&Receiver,
539 MessageSendInfo &MSI) = 0;
544 virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF,
547 MessageSendInfo &MSI) = 0;
560 llvm::Constant *MakeBitField(ArrayRef<bool> bits);
563 CGObjCGNU(CodeGenModule &cgm,
unsigned runtimeABIVersion,
564 unsigned protocolClassVersion,
unsigned classABI=1);
566 ConstantAddress GenerateConstantString(
const StringLiteral *SL)
override;
568 ConstantAddress GenerateConstantNumber(
const bool Value,
569 const QualType &Ty)
override;
570 ConstantAddress GenerateConstantNumber(
const llvm::APSInt &
Value,
571 const QualType &Ty)
override;
572 ConstantAddress GenerateConstantNumber(
const llvm::APFloat &
Value,
573 const QualType &Ty)
override;
575 GenerateConstantArray(
const ArrayRef<llvm::Constant *> &Objects)
override;
576 ConstantAddress GenerateConstantDictionary(
577 const ObjCDictionaryLiteral *E,
578 ArrayRef<std::pair<llvm::Constant *, llvm::Constant *>> KeysAndObjects)
582 GenerateMessageSend(CodeGenFunction &CGF, ReturnValueSlot Return,
583 QualType ResultType, Selector Sel,
584 llvm::Value *Receiver,
const CallArgList &CallArgs,
585 const ObjCInterfaceDecl *
Class,
586 const ObjCMethodDecl *
Method)
override;
588 GenerateMessageSendSuper(CodeGenFunction &CGF, ReturnValueSlot Return,
589 QualType ResultType, Selector Sel,
590 const ObjCInterfaceDecl *
Class,
591 bool isCategoryImpl, llvm::Value *Receiver,
592 bool IsClassMessage,
const CallArgList &CallArgs,
593 const ObjCMethodDecl *
Method)
override;
594 llvm::Value *GetClass(CodeGenFunction &CGF,
595 const ObjCInterfaceDecl *OID)
override;
596 llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel)
override;
597 Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel)
override;
598 llvm::Value *GetSelector(CodeGenFunction &CGF,
599 const ObjCMethodDecl *
Method)
override;
600 virtual llvm::Constant *GetConstantSelector(Selector Sel,
601 const std::string &TypeEncoding) {
602 llvm_unreachable(
"Runtime unable to generate constant selector");
604 llvm::Constant *GetConstantSelector(
const ObjCMethodDecl *M) {
608 llvm::Constant *GetEHType(QualType
T)
override;
610 llvm::Function *GenerateMethod(
const ObjCMethodDecl *OMD,
611 const ObjCContainerDecl *CD)
override;
614 llvm::DenseMap<const ObjCMethodDecl *, llvm::Function *>
615 DirectMethodDefinitions;
616 void GenerateDirectMethodsPreconditionCheck(
617 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
618 const ObjCContainerDecl *CD)
override;
619 void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
620 const ObjCMethodDecl *OMD,
621 const ObjCContainerDecl *CD)
override;
622 void GenerateCategory(
const ObjCCategoryImplDecl *CMD)
override;
623 void GenerateClass(
const ObjCImplementationDecl *ClassDecl)
override;
624 void RegisterAlias(
const ObjCCompatibleAliasDecl *OAD)
override;
625 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
626 const ObjCProtocolDecl *PD)
override;
627 void GenerateProtocol(
const ObjCProtocolDecl *PD)
override;
629 virtual llvm::Constant *GenerateProtocolRef(
const ObjCProtocolDecl *PD);
631 llvm::Constant *GetOrEmitProtocol(
const ObjCProtocolDecl *PD)
override {
632 return GenerateProtocolRef(PD);
635 llvm::Function *ModuleInitFunction()
override;
636 llvm::FunctionCallee GetPropertyGetFunction()
override;
637 llvm::FunctionCallee GetPropertySetFunction()
override;
638 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
640 llvm::FunctionCallee GetSetStructFunction()
override;
641 llvm::FunctionCallee GetGetStructFunction()
override;
642 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override;
643 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override;
644 llvm::FunctionCallee EnumerationMutationFunction()
override;
646 void EmitTryStmt(CodeGenFunction &CGF,
647 const ObjCAtTryStmt &S)
override;
648 void EmitSynchronizedStmt(CodeGenFunction &CGF,
649 const ObjCAtSynchronizedStmt &S)
override;
650 void EmitThrowStmt(CodeGenFunction &CGF,
651 const ObjCAtThrowStmt &S,
652 bool ClearInsertionPoint=
true)
override;
653 llvm::Value * EmitObjCWeakRead(CodeGenFunction &CGF,
654 Address AddrWeakObj)
override;
655 void EmitObjCWeakAssign(CodeGenFunction &CGF,
656 llvm::Value *src, Address dst)
override;
657 void EmitObjCGlobalAssign(CodeGenFunction &CGF,
658 llvm::Value *src, Address dest,
659 bool threadlocal=
false)
override;
660 void EmitObjCIvarAssign(CodeGenFunction &CGF, llvm::Value *src,
661 Address dest, llvm::Value *ivarOffset)
override;
662 void EmitObjCStrongCastAssign(CodeGenFunction &CGF,
663 llvm::Value *src, Address dest)
override;
664 void EmitGCMemmoveCollectable(CodeGenFunction &CGF, Address DestPtr,
666 llvm::Value *Size)
override;
667 LValue EmitObjCValueForIvar(CodeGenFunction &CGF, QualType ObjectTy,
668 llvm::Value *BaseValue,
const ObjCIvarDecl *Ivar,
669 unsigned CVRQualifiers)
override;
670 llvm::Value *EmitIvarOffset(CodeGenFunction &CGF,
672 const ObjCIvarDecl *Ivar)
override;
673 llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF)
override;
674 llvm::Constant *BuildGCBlockLayout(CodeGenModule &CGM,
675 const CGBlockInfo &blockInfo)
override {
678 llvm::Constant *BuildRCBlockLayout(CodeGenModule &CGM,
679 const CGBlockInfo &blockInfo)
override {
683 llvm::Constant *BuildByrefLayout(CodeGenModule &CGM, QualType
T)
override {
696class CGObjCGCC :
public CGObjCGNU {
699 LazyRuntimeFunction MsgLookupFn;
703 LazyRuntimeFunction MsgLookupSuperFn;
706 llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver,
707 llvm::Value *cmd, llvm::MDNode *node,
708 MessageSendInfo &MSI)
override {
709 CGBuilderTy &Builder = CGF.
Builder;
710 llvm::Value *args[] = {
711 EnforceType(Builder, Receiver, IdTy),
712 EnforceType(Builder, cmd, SelectorTy) };
714 imp->setMetadata(msgSendMDKind, node);
718 llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
719 llvm::Value *cmd, MessageSendInfo &MSI)
override {
720 CGBuilderTy &Builder = CGF.
Builder;
721 llvm::Value *lookupArgs[] = {
722 EnforceType(Builder, ObjCSuper.
emitRawPointer(CGF), PtrToObjCSuperTy),
728 CGObjCGCC(CodeGenModule &Mod) : CGObjCGNU(Mod, 8, 2) {
730 MsgLookupFn.init(&CGM,
"objc_msg_lookup", IMPTy, IdTy, SelectorTy);
732 MsgLookupSuperFn.init(&CGM,
"objc_msg_lookup_super", IMPTy,
733 PtrToObjCSuperTy, SelectorTy);
738class CGObjCGNUstep :
public CGObjCGNU {
741 LazyRuntimeFunction SlotLookupFn;
746 LazyRuntimeFunction SlotLookupSuperFn;
748 LazyRuntimeFunction SetPropertyAtomic;
750 LazyRuntimeFunction SetPropertyAtomicCopy;
752 LazyRuntimeFunction SetPropertyNonAtomic;
754 LazyRuntimeFunction SetPropertyNonAtomicCopy;
757 LazyRuntimeFunction CxxAtomicObjectGetFn;
760 LazyRuntimeFunction CxxAtomicObjectSetFn;
765 llvm::Type *SlotStructTy;
768 llvm::Constant *GetEHType(QualType
T)
override;
771 llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver,
772 llvm::Value *cmd, llvm::MDNode *node,
773 MessageSendInfo &MSI)
override {
774 CGBuilderTy &Builder = CGF.
Builder;
775 llvm::FunctionCallee LookupFn = SlotLookupFn;
778 RawAddress ReceiverPtr =
780 Builder.CreateStore(Receiver, ReceiverPtr);
787 self = llvm::ConstantPointerNull::get(IdTy);
791 if (
auto *LookupFn2 = dyn_cast<llvm::Function>(LookupFn.getCallee()))
792 LookupFn2->addParamAttr(
794 llvm::CaptureInfo::none()));
796 llvm::Value *args[] = {
797 EnforceType(Builder, ReceiverPtr.
getPointer(), PtrToIdTy),
798 EnforceType(Builder, cmd, SelectorTy),
799 EnforceType(Builder, self, IdTy)};
801 slot->setOnlyReadsMemory();
802 slot->setMetadata(msgSendMDKind, node);
805 llvm::Value *imp = Builder.CreateAlignedLoad(
806 IMPTy, Builder.CreateStructGEP(SlotStructTy, slot, 4),
811 Receiver = Builder.CreateLoad(ReceiverPtr,
true);
815 llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
817 MessageSendInfo &MSI)
override {
818 CGBuilderTy &Builder = CGF.
Builder;
821 llvm::CallInst *slot =
823 slot->setOnlyReadsMemory();
825 return Builder.CreateAlignedLoad(
826 IMPTy, Builder.CreateStructGEP(SlotStructTy, slot, 4),
831 CGObjCGNUstep(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 9, 3, 1) {}
832 CGObjCGNUstep(CodeGenModule &Mod,
unsigned ABI,
unsigned ProtocolABI,
834 CGObjCGNU(Mod, ABI, ProtocolABI, ClassABI) {
837 SlotStructTy = llvm::StructType::get(PtrTy, PtrTy, PtrTy, IntTy, IMPTy);
840 SlotLookupFn.init(&CGM,
"objc_msg_lookup_sender", SlotTy, PtrToIdTy,
843 SlotLookupSuperFn.init(&CGM,
"objc_slot_lookup_super", SlotTy,
844 PtrToObjCSuperTy, SelectorTy);
846 llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
847 if (usesCxxExceptions) {
849 EnterCatchFn.init(&CGM,
"__cxa_begin_catch", PtrTy, PtrTy);
851 ExitCatchFn.init(&CGM,
"__cxa_end_catch", VoidTy);
853 ExceptionReThrowFn.init(&CGM,
"__cxa_rethrow", VoidTy);
854 }
else if (usesSEHExceptions) {
856 ExceptionReThrowFn.init(&CGM,
"objc_exception_rethrow", VoidTy);
859 EnterCatchFn.init(&CGM,
"__cxa_begin_catch", PtrTy, PtrTy);
861 ExitCatchFn.init(&CGM,
"__cxa_end_catch", VoidTy);
863 ExceptionReThrowFn.init(&CGM,
"_Unwind_Resume_or_Rethrow", VoidTy,
865 }
else if (
R.getVersion() >= VersionTuple(1, 7)) {
867 EnterCatchFn.init(&CGM,
"objc_begin_catch", IdTy, PtrTy);
869 ExitCatchFn.init(&CGM,
"objc_end_catch", VoidTy);
871 ExceptionReThrowFn.init(&CGM,
"objc_exception_rethrow", VoidTy, PtrTy);
873 SetPropertyAtomic.init(&CGM,
"objc_setProperty_atomic", VoidTy, IdTy,
874 SelectorTy, IdTy, PtrDiffTy);
875 SetPropertyAtomicCopy.init(&CGM,
"objc_setProperty_atomic_copy", VoidTy,
876 IdTy, SelectorTy, IdTy, PtrDiffTy);
877 SetPropertyNonAtomic.init(&CGM,
"objc_setProperty_nonatomic", VoidTy,
878 IdTy, SelectorTy, IdTy, PtrDiffTy);
879 SetPropertyNonAtomicCopy.init(&CGM,
"objc_setProperty_nonatomic_copy",
880 VoidTy, IdTy, SelectorTy, IdTy, PtrDiffTy);
883 CxxAtomicObjectSetFn.init(&CGM,
"objc_setCppObjectAtomic", VoidTy, PtrTy,
887 CxxAtomicObjectGetFn.init(&CGM,
"objc_getCppObjectAtomic", VoidTy, PtrTy,
891 llvm::FunctionCallee GetCppAtomicObjectGetFunction()
override {
896 return CxxAtomicObjectGetFn;
899 llvm::FunctionCallee GetCppAtomicObjectSetFunction()
override {
904 return CxxAtomicObjectSetFn;
907 llvm::FunctionCallee GetOptimizedPropertySetFunction(
bool atomic,
908 bool copy)
override {
912 assert ((CGM.
getLangOpts().getGC() == LangOptions::NonGC));
919 if (copy)
return SetPropertyAtomicCopy;
920 return SetPropertyAtomic;
923 return copy ? SetPropertyNonAtomicCopy : SetPropertyNonAtomic;
930class CGObjCGNUstep2 :
public CGObjCGNUstep {
935 ClassReferenceSection,
938 ProtocolReferenceSection,
940 ConstantStringSection
945 ClassFlagMeta = (1 << 0),
948 ClassFlagInitialized = (1 << 8),
950 static const char *
const SectionsBaseNames[8];
951 static const char *
const PECOFFSectionsBaseNames[8];
952 template<SectionKind K>
953 std::string sectionName() {
954 if (CGM.
getTriple().isOSBinFormatCOFF()) {
955 std::string
name(PECOFFSectionsBaseNames[K]);
959 return SectionsBaseNames[K];
964 LazyRuntimeFunction MsgLookupSuperFn;
966 LazyRuntimeFunction SentInitializeFn;
970 bool EmittedProtocol =
false;
975 bool EmittedProtocolRef =
false;
979 bool EmittedClass =
false;
983 typedef std::pair<std::string, std::pair<llvm::GlobalVariable*, int>>
985 std::vector<EarlyInitPair> EarlyInitList;
987 std::string SymbolForClassRef(StringRef Name,
bool isWeak) {
989 return (ManglePublicSymbol(
"OBJC_WEAK_REF_CLASS_") + Name).str();
991 return (ManglePublicSymbol(
"OBJC_REF_CLASS_") + Name).str();
994 std::string SymbolForClass(StringRef Name) {
995 return (ManglePublicSymbol(
"OBJC_CLASS_") + Name).str();
997 void CallRuntimeFunction(CGBuilderTy &B, StringRef FunctionName,
998 ArrayRef<llvm::Value*> Args) {
999 SmallVector<llvm::Type *,8> Types;
1000 for (
auto *Arg : Args)
1001 Types.push_back(Arg->getType());
1002 llvm::FunctionType *FT = llvm::FunctionType::get(B.getVoidTy(), Types,
1005 B.CreateCall(Fn, Args);
1008 ConstantAddress GenerateConstantString(
const StringLiteral *SL)
override {
1014 llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
1015 if (old != ObjCStrings.end())
1016 return ConstantAddress(old->getValue(), IdElemTy, Align);
1023 (LiteralLength < 9) && !isNonASCII) {
1029 for (
unsigned i=0 ; i<LiteralLength ; i++)
1030 str |= ((uint64_t)SL->
getCodeUnit(i)) << ((64 - 4 - 3) - (i*7));
1032 str |= LiteralLength << 3;
1035 auto *ObjCStr = llvm::ConstantExpr::getIntToPtr(
1036 llvm::ConstantInt::get(Int64Ty, str), IdTy);
1037 ObjCStrings[Str] = ObjCStr;
1038 return ConstantAddress(ObjCStr, IdElemTy, Align);
1043 if (StringClass.empty()) StringClass =
"NSConstantString";
1045 std::string Sym = SymbolForClass(StringClass);
1047 llvm::Constant *
isa = TheModule.getNamedGlobal(Sym);
1050 isa =
new llvm::GlobalVariable(TheModule, IdTy,
false,
1051 llvm::GlobalValue::ExternalLinkage,
nullptr, Sym);
1052 if (CGM.
getTriple().isOSBinFormatCOFF()) {
1067 ConstantInitBuilder Builder(CGM);
1068 auto Fields = Builder.beginStruct();
1069 if (!CGM.
getTriple().isOSBinFormatCOFF()) {
1079 unsigned NumU8CodeUnits = Str.size();
1083 SmallVector<llvm::UTF16, 128> ToBuf(NumU8CodeUnits + 1);
1084 const llvm::UTF8 *FromPtr = (
const llvm::UTF8 *)Str.data();
1085 llvm::UTF16 *ToPtr = &ToBuf[0];
1086 (void)llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumU8CodeUnits,
1087 &ToPtr, ToPtr + NumU8CodeUnits, llvm::strictConversion);
1088 uint32_t StringLength = ToPtr - &ToBuf[0];
1092 Fields.
addInt(Int32Ty, 2);
1094 Fields.
addInt(Int32Ty, StringLength);
1096 Fields.
addInt(Int32Ty, StringLength * 2);
1098 Fields.
addInt(Int32Ty, 0);
1100 auto Arr = llvm::ArrayRef(&ToBuf[0], ToPtr + 1);
1101 auto *
C = llvm::ConstantDataArray::get(VMContext, Arr);
1102 auto *Buffer =
new llvm::GlobalVariable(TheModule,
C->getType(),
1103 true, llvm::GlobalValue::PrivateLinkage,
C,
".str");
1104 Buffer->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1108 Fields.
addInt(Int32Ty, 0);
1110 Fields.
addInt(Int32Ty, Str.size());
1112 Fields.
addInt(Int32Ty, Str.size());
1114 Fields.
addInt(Int32Ty, 0);
1116 Fields.
add(MakeConstantString(Str));
1118 std::string StringName;
1121 StringName =
".objc_str_";
1122 for (
unsigned char c : Str) {
1133 llvm::GlobalVariable *ObjCStrGV =
1135 isNamed ? StringRef(StringName) :
".objc_string",
1136 Align,
false,
isNamed ? llvm::GlobalValue::LinkOnceODRLinkage
1137 : llvm::GlobalValue::PrivateLinkage);
1138 ObjCStrGV->setSection(sectionName<ConstantStringSection>());
1140 ObjCStrGV->setComdat(TheModule.getOrInsertComdat(StringName));
1141 ObjCStrGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1143 if (CGM.
getTriple().isOSBinFormatCOFF()) {
1144 std::pair<llvm::GlobalVariable*, int> v{ObjCStrGV, 0};
1145 EarlyInitList.emplace_back(Sym, v);
1147 ObjCStrings[Str] = ObjCStrGV;
1148 ConstantStrings.push_back(ObjCStrGV);
1149 return ConstantAddress(ObjCStrGV, IdElemTy, Align);
1152 void PushProperty(ConstantArrayBuilder &PropertiesArray,
1153 const ObjCPropertyDecl *property,
1155 bool isSynthesized=
true,
bool
1156 isDynamic=
true)
override {
1165 auto Fields = PropertiesArray.
beginStruct(PropertyMetadataTy);
1168 std::string TypeStr =
1170 Fields.
add(MakeConstantString(TypeStr));
1171 std::string typeStr;
1173 Fields.
add(MakeConstantString(typeStr));
1174 auto addPropertyMethod = [&](
const ObjCMethodDecl *accessor) {
1177 Fields.
add(GetConstantSelector(accessor->getSelector(), TypeStr));
1179 Fields.
add(NULLPtr);
1188 GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods)
override {
1194 llvm::StructType *ObjCMethodDescTy =
1196 { PtrToInt8Ty, PtrToInt8Ty });
1198 ConstantInitBuilder Builder(CGM);
1205 auto MethodList = Builder.beginStruct();
1207 MethodList.addInt(IntTy, Methods.size());
1209 const llvm::DataLayout &DL = TheModule.getDataLayout();
1210 MethodList.addInt(IntTy, DL.getTypeSizeInBits(ObjCMethodDescTy) /
1213 auto MethodArray = MethodList.beginArray(ObjCMethodDescTy);
1214 for (
auto *M : Methods) {
1215 auto Method = MethodArray.beginStruct(ObjCMethodDescTy);
1216 Method.add(CGObjCGNU::GetConstantSelector(M));
1218 Method.finishAndAddTo(MethodArray);
1220 MethodArray.finishAndAddTo(MethodList);
1221 return MethodList.finishAndCreateGlobal(
".objc_protocol_method_list",
1224 llvm::Constant *GenerateCategoryProtocolList(
const ObjCCategoryDecl *OCD)
1227 auto RuntimeProtocols = GetRuntimeProtocolList(ReferencedProtocols.begin(),
1228 ReferencedProtocols.end());
1229 SmallVector<llvm::Constant *, 16> Protocols;
1230 for (
const auto *PI : RuntimeProtocols)
1231 Protocols.push_back(GenerateProtocolRef(PI));
1232 return GenerateProtocolList(Protocols);
1235 llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
1236 llvm::Value *cmd, MessageSendInfo &MSI)
override {
1238 CGBuilderTy &Builder = CGF.
Builder;
1239 llvm::Value *lookupArgs[] = {
1246 llvm::GlobalVariable *GetClassVar(StringRef Name,
bool isWeak=
false) {
1247 std::string SymbolName = SymbolForClassRef(Name, isWeak);
1248 auto *ClassSymbol = TheModule.getNamedGlobal(SymbolName);
1251 ClassSymbol =
new llvm::GlobalVariable(TheModule,
1252 IdTy,
false, llvm::GlobalValue::ExternalLinkage,
1253 nullptr, SymbolName);
1259 ClassSymbol->setInitializer(
new llvm::GlobalVariable(TheModule,
1260 Int8Ty,
false, llvm::GlobalValue::ExternalWeakLinkage,
1261 nullptr, SymbolForClass(Name)));
1263 if (CGM.
getTriple().isOSBinFormatCOFF()) {
1268 const ObjCInterfaceDecl *OID =
nullptr;
1270 if ((OID = dyn_cast<ObjCInterfaceDecl>(
Result)))
1276 assert(OID &&
"Failed to find ObjCInterfaceDecl");
1278 if (OIDDef !=
nullptr)
1281 auto Storage = llvm::GlobalValue::DefaultStorageClass;
1282 if (OID->
hasAttr<DLLImportAttr>())
1283 Storage = llvm::GlobalValue::DLLImportStorageClass;
1284 else if (OID->
hasAttr<DLLExportAttr>())
1285 Storage = llvm::GlobalValue::DLLExportStorageClass;
1290 assert(ClassSymbol->getName() == SymbolName);
1293 llvm::Value *GetClassNamed(CodeGenFunction &CGF,
1294 const std::string &Name,
1295 bool isWeak)
override {
1307 switch (Ownership) {
1324 llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
1325 ArrayRef<llvm::Constant *> IvarTypes,
1326 ArrayRef<llvm::Constant *> IvarOffsets,
1327 ArrayRef<llvm::Constant *> IvarAlign,
1328 ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership)
override {
1329 llvm_unreachable(
"Method should not be called!");
1332 llvm::Constant *GenerateEmptyProtocol(StringRef ProtocolName)
override {
1333 std::string Name = SymbolForProtocol(ProtocolName);
1334 auto *GV = TheModule.getGlobalVariable(Name);
1337 GV =
new llvm::GlobalVariable(TheModule, ProtocolTy,
false,
1338 llvm::GlobalValue::ExternalLinkage,
nullptr, Name);
1345 llvm::StringMap<llvm::Constant*> ExistingProtocolRefs;
1347 llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
1348 const ObjCProtocolDecl *PD)
override {
1350 auto *&Ref = ExistingProtocolRefs[Name];
1352 auto *&
Protocol = ExistingProtocols[Name];
1354 Protocol = GenerateProtocolRef(PD);
1355 std::string RefName = SymbolForProtocolRef(Name);
1356 assert(!TheModule.getGlobalVariable(RefName));
1358 auto GV =
new llvm::GlobalVariable(TheModule, ProtocolPtrTy,
false,
1359 llvm::GlobalValue::LinkOnceODRLinkage,
1361 GV->setComdat(TheModule.getOrInsertComdat(RefName));
1362 GV->setSection(sectionName<ProtocolReferenceSection>());
1366 EmittedProtocolRef =
true;
1371 llvm::Constant *GenerateProtocolList(ArrayRef<llvm::Constant*> Protocols) {
1372 llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(ProtocolPtrTy,
1374 llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
1376 ConstantInitBuilder builder(CGM);
1377 auto ProtocolBuilder = builder.beginStruct();
1378 ProtocolBuilder.addNullPointer(PtrTy);
1379 ProtocolBuilder.addInt(SizeTy, Protocols.size());
1380 ProtocolBuilder.add(ProtocolArray);
1381 return ProtocolBuilder.finishAndCreateGlobal(
".objc_protocol_list",
1385 void GenerateProtocol(
const ObjCProtocolDecl *PD)
override {
1388 llvm::Constant *GenerateProtocolRef(
const ObjCProtocolDecl *PD)
override {
1390 auto *&
Protocol = ExistingProtocols[ProtocolName];
1394 EmittedProtocol =
true;
1396 auto SymName = SymbolForProtocol(ProtocolName);
1397 auto *OldGV = TheModule.getGlobalVariable(SymName);
1407 Protocol =
new llvm::GlobalVariable(TheModule, ProtocolTy,
1409 llvm::GlobalValue::ExternalLinkage,
nullptr, SymName);
1413 SmallVector<llvm::Constant*, 16> Protocols;
1414 auto RuntimeProtocols =
1416 for (
const auto *PI : RuntimeProtocols)
1417 Protocols.push_back(GenerateProtocolRef(PI));
1418 llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
1421 llvm::Constant *InstanceMethodList, *OptionalInstanceMethodList;
1422 llvm::Constant *ClassMethodList, *OptionalClassMethodList;
1424 OptionalInstanceMethodList);
1425 EmitProtocolMethodList(PD->
class_methods(), ClassMethodList,
1426 OptionalClassMethodList);
1430 ConstantInitBuilder builder(CGM);
1431 auto ProtocolBuilder = builder.beginStruct();
1432 ProtocolBuilder.add(llvm::ConstantExpr::getIntToPtr(
1433 llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
1434 ProtocolBuilder.add(MakeConstantString(ProtocolName));
1435 ProtocolBuilder.add(ProtocolList);
1436 ProtocolBuilder.add(InstanceMethodList);
1437 ProtocolBuilder.add(ClassMethodList);
1438 ProtocolBuilder.add(OptionalInstanceMethodList);
1439 ProtocolBuilder.add(OptionalClassMethodList);
1441 ProtocolBuilder.add(GeneratePropertyList(
nullptr, PD,
false,
false));
1443 ProtocolBuilder.add(GeneratePropertyList(
nullptr, PD,
false,
true));
1445 ProtocolBuilder.add(GeneratePropertyList(
nullptr, PD,
true,
false));
1447 ProtocolBuilder.add(GeneratePropertyList(
nullptr, PD,
true,
true));
1449 auto *GV = ProtocolBuilder.finishAndCreateGlobal(SymName,
1451 GV->setSection(sectionName<ProtocolSection>());
1452 GV->setComdat(TheModule.getOrInsertComdat(SymName));
1454 OldGV->replaceAllUsesWith(GV);
1455 OldGV->removeFromParent();
1456 GV->setName(SymName);
1461 llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
1462 const std::string &TypeEncoding)
override {
1463 return GetConstantSelector(Sel, TypeEncoding);
1465 std::string GetSymbolNameForTypeEncoding(
const std::string &TypeEncoding) {
1466 std::string MangledTypes = std::string(TypeEncoding);
1472 llvm::replace(MangledTypes,
'@',
'\1');
1475 llvm::replace(MangledTypes,
'=',
'\2');
1476 return MangledTypes;
1478 llvm::Constant *GetTypeString(llvm::StringRef TypeEncoding) {
1479 if (TypeEncoding.empty())
1481 std::string MangledTypes =
1482 GetSymbolNameForTypeEncoding(std::string(TypeEncoding));
1483 std::string TypesVarName =
".objc_sel_types_" + MangledTypes;
1484 auto *TypesGlobal = TheModule.getGlobalVariable(TypesVarName);
1486 llvm::Constant *
Init = llvm::ConstantDataArray::getString(VMContext,
1488 auto *GV =
new llvm::GlobalVariable(TheModule,
Init->getType(),
1489 true, llvm::GlobalValue::LinkOnceODRLinkage,
Init, TypesVarName);
1490 GV->setComdat(TheModule.getOrInsertComdat(TypesVarName));
1491 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1496 llvm::Constant *GetConstantSelector(Selector Sel,
1497 const std::string &TypeEncoding)
override {
1498 std::string MangledTypes = GetSymbolNameForTypeEncoding(TypeEncoding);
1499 auto SelVarName = (StringRef(
".objc_selector_") + Sel.
getAsString() +
"_" +
1500 MangledTypes).str();
1501 if (
auto *GV = TheModule.getNamedGlobal(SelVarName))
1503 ConstantInitBuilder builder(CGM);
1504 auto SelBuilder = builder.beginStruct();
1505 SelBuilder.add(ExportUniqueString(Sel.
getAsString(),
".objc_sel_name_",
1507 SelBuilder.add(GetTypeString(TypeEncoding));
1508 auto *GV = SelBuilder.finishAndCreateGlobal(SelVarName,
1510 GV->setComdat(TheModule.getOrInsertComdat(SelVarName));
1511 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1512 GV->setSection(sectionName<SelectorSection>());
1515 llvm::StructType *emptyStruct =
nullptr;
1524 std::pair<llvm::Constant*,llvm::Constant*>
1525 GetSectionBounds(StringRef Section) {
1526 if (CGM.
getTriple().isOSBinFormatCOFF()) {
1527 if (emptyStruct ==
nullptr) {
1528 emptyStruct = llvm::StructType::create(
1529 VMContext, {},
".objc_section_sentinel",
true);
1531 auto ZeroInit = llvm::Constant::getNullValue(emptyStruct);
1532 auto Sym = [&](StringRef Prefix, StringRef SecSuffix) {
1533 auto *Sym =
new llvm::GlobalVariable(TheModule, emptyStruct,
1535 llvm::GlobalValue::LinkOnceODRLinkage, ZeroInit, Prefix +
1537 Sym->setVisibility(llvm::GlobalValue::HiddenVisibility);
1538 Sym->setSection((Section + SecSuffix).str());
1539 Sym->setComdat(TheModule.getOrInsertComdat((Prefix +
1544 return { Sym(
"__start_",
"$a"), Sym(
"__stop",
"$z") };
1546 auto *Start =
new llvm::GlobalVariable(TheModule, PtrTy,
1548 llvm::GlobalValue::ExternalLinkage,
nullptr, StringRef(
"__start_") +
1550 Start->setVisibility(llvm::GlobalValue::HiddenVisibility);
1551 auto *Stop =
new llvm::GlobalVariable(TheModule, PtrTy,
1553 llvm::GlobalValue::ExternalLinkage,
nullptr, StringRef(
"__stop_") +
1555 Stop->setVisibility(llvm::GlobalValue::HiddenVisibility);
1556 return { Start, Stop };
1558 CatchTypeInfo getCatchAllTypeInfo()
override {
1561 llvm::Function *ModuleInitFunction()
override {
1562 llvm::Function *LoadFunction = llvm::Function::Create(
1563 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
false),
1564 llvm::GlobalValue::LinkOnceODRLinkage,
".objcv2_load_function",
1566 LoadFunction->setVisibility(llvm::GlobalValue::HiddenVisibility);
1567 LoadFunction->setComdat(TheModule.getOrInsertComdat(
".objcv2_load_function"));
1569 llvm::BasicBlock *EntryBB =
1570 llvm::BasicBlock::Create(VMContext,
"entry", LoadFunction);
1571 CGBuilderTy B(CGM, VMContext);
1572 B.SetInsertPoint(EntryBB);
1573 ConstantInitBuilder builder(CGM);
1574 auto InitStructBuilder = builder.beginStruct();
1575 InitStructBuilder.addInt(Int64Ty, 0);
1576 auto §ionVec = CGM.
getTriple().isOSBinFormatCOFF() ? PECOFFSectionsBaseNames : SectionsBaseNames;
1577 for (
auto *s : sectionVec) {
1578 auto bounds = GetSectionBounds(s);
1579 InitStructBuilder.add(bounds.first);
1580 InitStructBuilder.add(bounds.second);
1582 auto *InitStruct = InitStructBuilder.finishAndCreateGlobal(
".objc_init",
1584 InitStruct->setVisibility(llvm::GlobalValue::HiddenVisibility);
1585 InitStruct->setComdat(TheModule.getOrInsertComdat(
".objc_init"));
1587 CallRuntimeFunction(B,
"__objc_load", {InitStruct});;
1594 auto *InitVar =
new llvm::GlobalVariable(TheModule, LoadFunction->getType(),
1595 false, llvm::GlobalValue::LinkOnceAnyLinkage,
1596 LoadFunction,
".objc_ctor");
1599 assert(InitVar->getName() ==
".objc_ctor");
1605 if (CGM.
getTriple().isOSBinFormatCOFF())
1606 InitVar->setSection(
".CRT$XCLz");
1610 InitVar->setSection(
".init_array");
1612 InitVar->setSection(
".ctors");
1614 InitVar->setVisibility(llvm::GlobalValue::HiddenVisibility);
1615 InitVar->setComdat(TheModule.getOrInsertComdat(
".objc_ctor"));
1617 for (
auto *
C : Categories) {
1619 Cat->setSection(sectionName<CategorySection>());
1622 auto createNullGlobal = [&](StringRef Name, ArrayRef<llvm::Constant*>
Init,
1623 StringRef Section) {
1624 auto nullBuilder = builder.beginStruct();
1625 for (
auto *F :
Init)
1627 auto GV = nullBuilder.finishAndCreateGlobal(Name, CGM.
getPointerAlign(),
1628 false, llvm::GlobalValue::LinkOnceODRLinkage);
1629 GV->setSection(Section);
1630 GV->setComdat(TheModule.getOrInsertComdat(Name));
1631 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
1635 for (
auto clsAlias : ClassAliases)
1636 createNullGlobal(std::string(
".objc_class_alias") +
1637 clsAlias.second, { MakeConstantString(clsAlias.second),
1638 GetClassVar(clsAlias.first) }, sectionName<ClassAliasSection>());
1643 if (!CGM.
getTriple().isOSBinFormatCOFF()) {
1644 createNullGlobal(
".objc_null_selector", {NULLPtr, NULLPtr},
1645 sectionName<SelectorSection>());
1646 if (Categories.empty())
1647 createNullGlobal(
".objc_null_category", {NULLPtr, NULLPtr,
1648 NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr},
1649 sectionName<CategorySection>());
1650 if (!EmittedClass) {
1651 createNullGlobal(
".objc_null_cls_init_ref", NULLPtr,
1652 sectionName<ClassSection>());
1653 createNullGlobal(
".objc_null_class_ref", { NULLPtr, NULLPtr },
1654 sectionName<ClassReferenceSection>());
1656 if (!EmittedProtocol)
1657 createNullGlobal(
".objc_null_protocol", {NULLPtr, NULLPtr, NULLPtr,
1658 NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr,
1659 NULLPtr}, sectionName<ProtocolSection>());
1660 if (!EmittedProtocolRef)
1661 createNullGlobal(
".objc_null_protocol_ref", {NULLPtr},
1662 sectionName<ProtocolReferenceSection>());
1663 if (ClassAliases.empty())
1664 createNullGlobal(
".objc_null_class_alias", { NULLPtr, NULLPtr },
1665 sectionName<ClassAliasSection>());
1666 if (ConstantStrings.empty()) {
1667 auto i32Zero = llvm::ConstantInt::get(Int32Ty, 0);
1668 createNullGlobal(
".objc_null_constant_string", { NULLPtr, i32Zero,
1669 i32Zero, i32Zero, i32Zero, NULLPtr },
1670 sectionName<ConstantStringSection>());
1673 ConstantStrings.clear();
1677 if (EarlyInitList.size() > 0) {
1678 auto *
Init = llvm::Function::Create(llvm::FunctionType::get(CGM.
VoidTy,
1679 {}), llvm::GlobalValue::InternalLinkage,
".objc_early_init",
1681 llvm::IRBuilder<> b(llvm::BasicBlock::Create(CGM.
getLLVMContext(),
"entry",
1683 for (
const auto &lateInit : EarlyInitList) {
1684 auto *global = TheModule.getGlobalVariable(lateInit.first);
1686 llvm::GlobalVariable *GV = lateInit.second.first;
1687 b.CreateAlignedStore(
1689 b.CreateStructGEP(GV->getValueType(), GV, lateInit.second.second),
1696 auto *InitVar =
new llvm::GlobalVariable(CGM.
getModule(),
Init->getType(),
1697 true, llvm::GlobalValue::InternalLinkage,
1698 Init,
".objc_early_init_ptr");
1699 InitVar->setSection(
".CRT$XCLb");
1706 std::string GetIVarOffsetVariableName(
const ObjCInterfaceDecl *ID,
1707 const ObjCIvarDecl *Ivar)
override {
1708 std::string TypeEncoding;
1710 TypeEncoding = GetSymbolNameForTypeEncoding(TypeEncoding);
1711 const std::string Name =
"__objc_ivar_offset_" +
ID->getNameAsString()
1715 llvm::Value *EmitIvarOffset(CodeGenFunction &CGF,
1717 const ObjCIvarDecl *Ivar)
override {
1718 const ObjCInterfaceDecl *ContainingInterface =
1720 const std::string Name =
1721 GetIVarOffsetVariableName(ContainingInterface, Ivar);
1722 llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
1723 if (!IvarOffsetPointer) {
1724 IvarOffsetPointer =
new llvm::GlobalVariable(TheModule, IntTy,
false,
1725 llvm::GlobalValue::ExternalLinkage,
nullptr, Name);
1731 llvm::Value *Offset =
1733 if (Offset->getType() != PtrDiffTy)
1734 Offset = CGF.
Builder.CreateZExtOrBitCast(Offset, PtrDiffTy);
1737 void GenerateClass(
const ObjCImplementationDecl *OID)
override {
1739 bool IsCOFF = CGM.
getTriple().isOSBinFormatCOFF();
1742 ObjCInterfaceDecl *classDecl =
1745 auto *classNameConstant = MakeConstantString(className);
1747 ConstantInitBuilder builder(CGM);
1748 auto metaclassFields = builder.beginStruct();
1750 metaclassFields.addNullPointer(PtrTy);
1752 metaclassFields.addNullPointer(PtrTy);
1754 metaclassFields.add(classNameConstant);
1756 metaclassFields.addInt(LongTy, 0);
1759 metaclassFields.addInt(LongTy, ClassFlags::ClassFlagMeta);
1763 metaclassFields.addInt(LongTy, 0);
1765 metaclassFields.addNullPointer(PtrTy);
1770 metaclassFields.addNullPointer(PtrTy);
1772 SmallVector<ObjCMethodDecl*, 16> ClassMethods;
1775 metaclassFields.add(
1776 GenerateMethodList(className,
"", ClassMethods,
true));
1779 metaclassFields.addNullPointer(PtrTy);
1781 metaclassFields.addNullPointer(PtrTy);
1783 metaclassFields.addNullPointer(PtrTy);
1785 metaclassFields.addNullPointer(PtrTy);
1787 metaclassFields.addNullPointer(PtrTy);
1789 metaclassFields.addNullPointer(PtrTy);
1791 metaclassFields.addNullPointer(PtrTy);
1793 metaclassFields.addInt(LongTy, 0);
1795 metaclassFields.add(GeneratePropertyList(OID, classDecl,
true));
1797 auto *metaclass = metaclassFields.finishAndCreateGlobal(
1798 ManglePublicSymbol(
"OBJC_METACLASS_") + className,
1801 auto classFields = builder.beginStruct();
1803 classFields.add(metaclass);
1806 const ObjCInterfaceDecl * SuperClassDecl =
1808 llvm::Constant *SuperClass =
nullptr;
1809 if (SuperClassDecl) {
1810 auto SuperClassName = SymbolForClass(SuperClassDecl->
getNameAsString());
1811 SuperClass = TheModule.getNamedGlobal(SuperClassName);
1814 SuperClass =
new llvm::GlobalVariable(TheModule, PtrTy,
false,
1815 llvm::GlobalValue::ExternalLinkage,
nullptr, SuperClassName);
1817 auto Storage = llvm::GlobalValue::DefaultStorageClass;
1818 if (SuperClassDecl->
hasAttr<DLLImportAttr>())
1819 Storage = llvm::GlobalValue::DLLImportStorageClass;
1820 else if (SuperClassDecl->
hasAttr<DLLExportAttr>())
1821 Storage = llvm::GlobalValue::DLLExportStorageClass;
1827 classFields.add(SuperClass);
1829 classFields.addNullPointer(PtrTy);
1831 classFields.addNullPointer(PtrTy);
1833 classFields.
add(classNameConstant);
1835 classFields.addInt(LongTy, 0);
1838 classFields.addInt(LongTy, 0);
1840 int superInstanceSize = !SuperClassDecl ? 0 :
1853 classFields.addNullPointer(PtrTy);
1858 const llvm::DataLayout &DL = TheModule.getDataLayout();
1860 ConstantInitBuilder b(CGM);
1861 auto ivarListBuilder = b.beginStruct();
1863 ivarListBuilder.addInt(IntTy, ivar_count);
1865 llvm::StructType *ObjCIvarTy = llvm::StructType::get(
1871 ivarListBuilder.addInt(SizeTy, DL.getTypeSizeInBits(ObjCIvarTy) /
1874 auto ivarArrayBuilder = ivarListBuilder.beginArray();
1877 auto ivarTy = IVD->getType();
1878 auto ivarBuilder = ivarArrayBuilder.beginStruct();
1880 ivarBuilder.add(MakeConstantString(IVD->getNameAsString()));
1882 std::string TypeStr;
1885 ivarBuilder.add(MakeConstantString(TypeStr));
1887 uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
1888 int64_t Offset =
static_cast<int64_t>(BaseOffset) - superInstanceSize;
1889 llvm::Constant *OffsetValue =
1890 llvm::ConstantInt::getSigned(IntTy, Offset);
1891 std::string OffsetName = GetIVarOffsetVariableName(classDecl, IVD);
1892 llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName);
1894 OffsetVar->setInitializer(OffsetValue);
1896 OffsetVar =
new llvm::GlobalVariable(TheModule, IntTy,
1897 false, llvm::GlobalValue::ExternalLinkage,
1898 OffsetValue, OffsetName);
1899 auto ivarVisibility =
1903 llvm::GlobalValue::HiddenVisibility :
1904 llvm::GlobalValue::DefaultVisibility;
1905 OffsetVar->setVisibility(ivarVisibility);
1906 if (ivarVisibility != llvm::GlobalValue::HiddenVisibility)
1908 ivarBuilder.add(OffsetVar);
1910 ivarBuilder.addInt(Int32Ty,
1921 ivarBuilder.addInt(Int32Ty,
1922 (align << 3) | (1<<2) |
1923 FlagsForOwnership(ivarTy.getQualifiers().getObjCLifetime()));
1924 ivarBuilder.finishAndAddTo(ivarArrayBuilder);
1926 ivarArrayBuilder.finishAndAddTo(ivarListBuilder);
1927 auto ivarList = ivarListBuilder.finishAndCreateGlobal(
".objc_ivar_list",
1929 llvm::GlobalValue::PrivateLinkage);
1930 classFields.add(ivarList);
1933 SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
1934 InstanceMethods.insert(InstanceMethods.begin(), OID->
instmeth_begin(),
1937 if (propImpl->getPropertyImplementation() ==
1939 auto addIfExists = [&](
const ObjCMethodDecl *OMD) {
1940 if (OMD && OMD->hasBody())
1941 InstanceMethods.push_back(OMD);
1943 addIfExists(propImpl->getGetterMethodDecl());
1944 addIfExists(propImpl->getSetterMethodDecl());
1947 if (InstanceMethods.size() == 0)
1948 classFields.addNullPointer(PtrTy);
1951 GenerateMethodList(className,
"", InstanceMethods,
false));
1954 classFields.addNullPointer(PtrTy);
1956 classFields.addNullPointer(PtrTy);
1958 classFields.addNullPointer(PtrTy);
1960 classFields.addNullPointer(PtrTy);
1962 classFields.addNullPointer(PtrTy);
1964 auto RuntimeProtocols =
1967 SmallVector<llvm::Constant *, 16> Protocols;
1968 for (
const auto *I : RuntimeProtocols)
1969 Protocols.push_back(GenerateProtocolRef(I));
1971 if (Protocols.empty())
1972 classFields.addNullPointer(PtrTy);
1974 classFields.add(GenerateProtocolList(Protocols));
1976 classFields.addNullPointer(PtrTy);
1978 classFields.addInt(LongTy, 0);
1980 classFields.add(GeneratePropertyList(OID, classDecl));
1982 llvm::GlobalVariable *classStruct =
1983 classFields.finishAndCreateGlobal(SymbolForClass(className),
1986 auto *classRefSymbol = GetClassVar(className);
1987 classRefSymbol->setSection(sectionName<ClassReferenceSection>());
1988 classRefSymbol->setInitializer(classStruct);
1993 classStruct->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
1998 std::pair<llvm::GlobalVariable*, int> v{classStruct, 1};
1999 EarlyInitList.emplace_back(std::string(SuperClass->getName()),
2008 if (ClassPtrAlias) {
2009 ClassPtrAlias->replaceAllUsesWith(classStruct);
2010 ClassPtrAlias->eraseFromParent();
2011 ClassPtrAlias =
nullptr;
2013 if (
auto Placeholder =
2014 TheModule.getNamedGlobal(SymbolForClass(className)))
2015 if (Placeholder != classStruct) {
2016 Placeholder->replaceAllUsesWith(classStruct);
2017 Placeholder->eraseFromParent();
2018 classStruct->setName(SymbolForClass(className));
2020 if (MetaClassPtrAlias) {
2021 MetaClassPtrAlias->replaceAllUsesWith(metaclass);
2022 MetaClassPtrAlias->eraseFromParent();
2023 MetaClassPtrAlias =
nullptr;
2025 assert(classStruct->getName() == SymbolForClass(className));
2027 auto classInitRef =
new llvm::GlobalVariable(TheModule,
2028 classStruct->getType(),
false, llvm::GlobalValue::ExternalLinkage,
2029 classStruct, ManglePublicSymbol(
"OBJC_INIT_CLASS_") + className);
2030 classInitRef->setSection(sectionName<ClassSection>());
2033 EmittedClass =
true;
2036 CGObjCGNUstep2(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 10, 4, 2) {
2037 MsgLookupSuperFn.init(&CGM,
"objc_msg_lookup_super", IMPTy,
2038 PtrToObjCSuperTy, SelectorTy);
2039 SentInitializeFn.init(&CGM,
"objc_send_initialize",
2040 llvm::Type::getVoidTy(VMContext), IdTy);
2049 PropertyMetadataTy =
2051 { PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
2054 void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
2055 const ObjCMethodDecl *OMD,
2056 const ObjCContainerDecl *CD)
override {
2058 bool ReceiverCanBeNull =
true;
2060 auto selfValue = Builder.CreateLoad(selfAddr);
2085 ReceiverCanBeNull = isWeakLinkedClass(OID);
2089 if (ReceiverCanBeNull) {
2090 llvm::BasicBlock *SelfIsNilBlock =
2092 llvm::BasicBlock *ContBlock =
2097 auto Zero = llvm::ConstantPointerNull::get(selfTy);
2099 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue,
Zero),
2100 SelfIsNilBlock, ContBlock,
2101 MDHelper.createUnlikelyBranchWeights());
2107 Builder.SetInsertPoint(SelfIsNilBlock);
2108 if (!retTy->isVoidType()) {
2116 Builder.SetInsertPoint(ContBlock);
2122 llvm::StructType::get(PtrTy, PtrTy, PtrTy, LongTy, LongTy);
2129 llvm::Value *Val = Builder.CreateStructGEP(classStart, selfValue, 4);
2131 astContext.getTypeAlign(astContext.UnsignedLongTy));
2132 auto flags = Builder.CreateLoad(Address{Val, LongTy, Align});
2133 auto isInitialized =
2134 Builder.CreateAnd(flags, ClassFlags::ClassFlagInitialized);
2135 llvm::BasicBlock *notInitializedBlock =
2137 llvm::BasicBlock *initializedBlock =
2139 Builder.CreateCondBr(Builder.CreateICmpEQ(isInitialized, Zeros[0]),
2140 notInitializedBlock, initializedBlock,
2141 MDHelper.createUnlikelyBranchWeights());
2143 Builder.SetInsertPoint(notInitializedBlock);
2145 Builder.CreateBr(initializedBlock);
2147 Builder.SetInsertPoint(initializedBlock);
2155 Builder.CreateStore(GetSelector(CGF, OMD),
2161const char *
const CGObjCGNUstep2::SectionsBaseNames[8] =
2168"__objc_protocol_refs",
2169"__objc_class_aliases",
2170"__objc_constant_string"
2173const char *
const CGObjCGNUstep2::PECOFFSectionsBaseNames[8] =
2186class CGObjCObjFW:
public CGObjCGNU {
2190 LazyRuntimeFunction MsgLookupFn;
2193 LazyRuntimeFunction MsgLookupFnSRet;
2197 LazyRuntimeFunction MsgLookupSuperFn, MsgLookupSuperFnSRet;
2199 llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver,
2200 llvm::Value *cmd, llvm::MDNode *node,
2201 MessageSendInfo &MSI)
override {
2202 CGBuilderTy &Builder = CGF.
Builder;
2203 llvm::Value *args[] = {
2204 EnforceType(Builder, Receiver, IdTy),
2205 EnforceType(Builder, cmd, SelectorTy) };
2207 llvm::CallBase *imp;
2213 imp->setMetadata(msgSendMDKind, node);
2217 llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
2218 llvm::Value *cmd, MessageSendInfo &MSI)
override {
2219 CGBuilderTy &Builder = CGF.
Builder;
2220 llvm::Value *lookupArgs[] = {
2221 EnforceType(Builder, ObjCSuper.
emitRawPointer(CGF), PtrToObjCSuperTy),
2231 llvm::Value *GetClassNamed(CodeGenFunction &CGF,
const std::string &Name,
2232 bool isWeak)
override {
2234 return CGObjCGNU::GetClassNamed(CGF, Name, isWeak);
2237 std::string SymbolName =
"_OBJC_CLASS_" + Name;
2238 llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(SymbolName);
2240 ClassSymbol =
new llvm::GlobalVariable(TheModule, LongTy,
false,
2241 llvm::GlobalValue::ExternalLinkage,
2242 nullptr, SymbolName);
2246 void GenerateDirectMethodPrologue(
2247 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
2248 const ObjCContainerDecl *CD)
override {
2250 bool ReceiverCanBeNull =
true;
2252 auto selfValue = Builder.CreateLoad(selfAddr);
2271 "GenerateDirectMethod() should be called with the Class Interface");
2284 result = GeneratePossiblySpecializedMessageSend(
2285 CGF, ReturnValueSlot(), ResultType, SelfSel, selfValue, Args, OID,
2292 ReceiverCanBeNull = isWeakLinkedClass(OID);
2295 if (ReceiverCanBeNull) {
2296 llvm::BasicBlock *SelfIsNilBlock =
2298 llvm::BasicBlock *ContBlock =
2303 auto Zero = llvm::ConstantPointerNull::get(selfTy);
2306 Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue,
Zero),
2307 SelfIsNilBlock, ContBlock,
2308 MDHelper.createUnlikelyBranchWeights());
2314 Builder.SetInsertPoint(SelfIsNilBlock);
2315 if (!retTy->isVoidType()) {
2323 Builder.SetInsertPoint(ContBlock);
2331 Builder.CreateStore(GetSelector(CGF, OMD),
2337 CGObjCObjFW(CodeGenModule &Mod): CGObjCGNU(Mod, 9, 3) {
2339 MsgLookupFn.init(&CGM,
"objc_msg_lookup", IMPTy, IdTy, SelectorTy);
2340 MsgLookupFnSRet.init(&CGM,
"objc_msg_lookup_stret", IMPTy, IdTy,
2343 MsgLookupSuperFn.init(&CGM,
"objc_msg_lookup_super", IMPTy,
2344 PtrToObjCSuperTy, SelectorTy);
2345 MsgLookupSuperFnSRet.init(&CGM,
"objc_msg_lookup_super_stret", IMPTy,
2346 PtrToObjCSuperTy, SelectorTy);
2354void CGObjCGNU::EmitClassRef(
const std::string &className) {
2355 std::string symbolRef =
"__objc_class_ref_" + className;
2357 if (TheModule.getGlobalVariable(symbolRef))
2359 std::string symbolName =
"__objc_class_name_" + className;
2360 llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName);
2362 ClassSymbol =
new llvm::GlobalVariable(TheModule, LongTy,
false,
2363 llvm::GlobalValue::ExternalLinkage,
2364 nullptr, symbolName);
2366 new llvm::GlobalVariable(TheModule, ClassSymbol->getType(),
true,
2367 llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef);
2370CGObjCGNU::CGObjCGNU(CodeGenModule &cgm,
unsigned runtimeABIVersion,
2371 unsigned protocolClassVersion,
unsigned classABI)
2372 : CGObjCRuntime(cgm), TheModule(CGM.getModule()),
2373 VMContext(cgm.getLLVMContext()), ClassPtrAlias(
nullptr),
2374 MetaClassPtrAlias(
nullptr), RuntimeVersion(runtimeABIVersion),
2375 ProtocolVersion(protocolClassVersion), ClassABIVersion(classABI) {
2377 msgSendMDKind = VMContext.getMDKindID(
"GNUObjCMessageSend");
2395 Int8Ty = llvm::Type::getInt8Ty(VMContext);
2400 PtrToInt8Ty = PtrTy;
2401 ProtocolPtrTy = PtrTy;
2403 Zeros[0] = llvm::ConstantInt::get(LongTy, 0);
2404 Zeros[1] = Zeros[0];
2405 NULLPtr = llvm::ConstantPointerNull::get(PtrToInt8Ty);
2409 SelectorTy = PtrToInt8Ty;
2410 SelectorElemTy = Int8Ty;
2416 Int32Ty = llvm::Type::getInt32Ty(VMContext);
2417 Int64Ty = llvm::Type::getInt64Ty(VMContext);
2420 CGM.
getDataLayout().getPointerSizeInBits() == 32 ? Int32Ty : Int64Ty;
2435 ProtocolTy = llvm::StructType::get(IdTy,
2457 PropertyMetadataTy = llvm::StructType::get(CGM.
getLLVMContext(), {
2458 PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty,
2459 PtrToInt8Ty, PtrToInt8Ty });
2461 ObjCSuperTy = llvm::StructType::get(IdTy, IdTy);
2462 PtrToObjCSuperTy = PtrTy;
2464 llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
2467 ExceptionThrowFn.init(&CGM,
"objc_exception_throw", VoidTy, IdTy);
2468 ExceptionReThrowFn.init(&CGM,
2469 usesCxxExceptions ?
"objc_exception_rethrow"
2470 :
"objc_exception_throw",
2473 SyncEnterFn.init(&CGM,
"objc_sync_enter", IntTy, IdTy);
2475 SyncExitFn.init(&CGM,
"objc_sync_exit", IntTy, IdTy);
2478 EnumerationMutationFn.init(&CGM,
"objc_enumerationMutation", VoidTy, IdTy);
2481 GetPropertyFn.init(&CGM,
"objc_getProperty", IdTy, IdTy, SelectorTy,
2484 SetPropertyFn.init(&CGM,
"objc_setProperty", VoidTy, IdTy, SelectorTy,
2485 PtrDiffTy, IdTy, BoolTy, BoolTy);
2487 GetStructPropertyFn.init(&CGM,
"objc_getPropertyStruct", VoidTy, PtrTy, PtrTy,
2488 PtrDiffTy, BoolTy, BoolTy);
2490 SetStructPropertyFn.init(&CGM,
"objc_setPropertyStruct", VoidTy, PtrTy, PtrTy,
2491 PtrDiffTy, BoolTy, BoolTy);
2498 RuntimeVersion = 10;
2513 IvarAssignFn.init(&CGM,
"objc_assign_ivar", IdTy, IdTy, IdTy, PtrDiffTy);
2515 StrongCastAssignFn.init(&CGM,
"objc_assign_strongCast", IdTy, IdTy,
2518 GlobalAssignFn.init(&CGM,
"objc_assign_global", IdTy, IdTy, PtrToIdTy);
2520 WeakAssignFn.init(&CGM,
"objc_assign_weak", IdTy, IdTy, PtrToIdTy);
2522 WeakReadFn.init(&CGM,
"objc_read_weak", IdTy, PtrToIdTy);
2524 MemMoveFn.init(&CGM,
"objc_memmove_collectable", PtrTy, PtrTy, PtrTy,
2530 const std::string &Name,
bool isWeak) {
2531 llvm::Constant *ClassName = MakeConstantString(Name);
2543 llvm::FunctionType::get(IdTy, PtrToInt8Ty,
true),
"objc_lookup_class");
2549llvm::Value *CGObjCGNU::GetClass(CodeGenFunction &CGF,
2550 const ObjCInterfaceDecl *OID) {
2553 if (
auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(
Value))
2558llvm::Value *CGObjCGNU::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
2559 auto *
Value = GetClassNamed(CGF,
"NSAutoreleasePool",
false);
2560 if (CGM.
getTriple().isOSBinFormatCOFF()) {
2561 if (
auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(
Value)) {
2566 const VarDecl *VD =
nullptr;
2568 if ((VD = dyn_cast<VarDecl>(
Result)))
2577llvm::Value *CGObjCGNU::GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
2578 const std::string &TypeEncoding) {
2579 SmallVectorImpl<TypedSelector> &Types = SelectorTable[Sel];
2580 llvm::GlobalAlias *SelValue =
nullptr;
2582 for (
const TypedSelector &
Type : Types) {
2583 if (
Type.first == TypeEncoding) {
2584 SelValue =
Type.second;
2589 SelValue = llvm::GlobalAlias::create(SelectorElemTy, 0,
2590 llvm::GlobalValue::PrivateLinkage,
2593 Types.emplace_back(TypeEncoding, SelValue);
2599Address CGObjCGNU::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
2600 llvm::Value *SelValue = GetSelector(CGF, Sel);
2610llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel) {
2611 return GetTypedSelector(CGF, Sel, std::string());
2614llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF,
2615 const ObjCMethodDecl *
Method) {
2617 return GetTypedSelector(CGF,
Method->getSelector(), SelTypes);
2620llvm::Constant *CGObjCGNU::GetEHType(QualType
T) {
2627 return MakeConstantString(
"@id");
2634 const ObjCObjectPointerType *OPT =
T->
getAs<ObjCObjectPointerType>();
2635 assert(OPT &&
"Invalid @catch type.");
2636 const ObjCInterfaceDecl *IDecl = OPT->
getObjectType()->getInterface();
2637 assert(IDecl &&
"Invalid @catch type.");
2641llvm::Constant *CGObjCGNUstep::GetEHType(QualType
T) {
2642 if (usesSEHExceptions)
2645 if (!CGM.
getLangOpts().CPlusPlus && !usesCxxExceptions)
2646 return CGObjCGNU::GetEHType(
T);
2654 llvm::Constant *IDEHType =
2655 CGM.
getModule().getGlobalVariable(
"__objc_id_type_info");
2658 new llvm::GlobalVariable(CGM.
getModule(), PtrToInt8Ty,
2660 llvm::GlobalValue::ExternalLinkage,
2661 nullptr,
"__objc_id_type_info");
2665 const ObjCObjectPointerType *PT =
2666 T->
getAs<ObjCObjectPointerType>();
2667 assert(PT &&
"Invalid @catch type.");
2669 assert(IT &&
"Invalid @catch type.");
2670 std::string className =
2673 std::string typeinfoName =
"__objc_eh_typeinfo_" + className;
2676 if (llvm::Constant *typeinfo = TheModule.getGlobalVariable(typeinfoName))
2684 const char *vtableName =
"_ZTVN7gnustep7libobjc22__objc_class_type_infoE";
2685 auto *Vtable = TheModule.getGlobalVariable(vtableName);
2687 Vtable =
new llvm::GlobalVariable(TheModule, PtrToInt8Ty,
true,
2688 llvm::GlobalValue::ExternalLinkage,
2689 nullptr, vtableName);
2691 llvm::Constant *Two = llvm::ConstantInt::get(IntTy, 2);
2693 llvm::ConstantExpr::getGetElementPtr(Vtable->getValueType(), Vtable, Two);
2695 llvm::Constant *typeName =
2696 ExportUniqueString(className,
"__objc_eh_typename_");
2698 ConstantInitBuilder builder(CGM);
2699 auto fields = builder.beginStruct();
2700 fields.add(BVtable);
2701 fields.add(typeName);
2702 llvm::Constant *TI =
2703 fields.finishAndCreateGlobal(
"__objc_eh_typeinfo_" + className,
2706 llvm::GlobalValue::LinkOnceODRLinkage);
2711ConstantAddress CGObjCGNU::GenerateConstantString(
const StringLiteral *SL) {
2713 std::string Str = SL->
getString().str();
2717 llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
2718 if (old != ObjCStrings.end())
2719 return ConstantAddress(old->getValue(), Int8Ty, Align);
2723 if (StringClass.empty()) StringClass =
"NSConstantString";
2725 std::string Sym =
"_OBJC_CLASS_";
2728 llvm::Constant *
isa = TheModule.getNamedGlobal(Sym);
2731 isa =
new llvm::GlobalVariable(TheModule, IdTy,
false,
2732 llvm::GlobalValue::ExternalWeakLinkage,
2735 ConstantInitBuilder Builder(CGM);
2736 auto Fields = Builder.beginStruct();
2738 Fields.
add(MakeConstantString(Str));
2739 Fields.
addInt(IntTy, Str.size());
2741 ObjCStrings[Str] = ObjCStr;
2742 ConstantStrings.push_back(ObjCStr);
2743 return ConstantAddress(ObjCStr, Int8Ty, Align);
2746ConstantAddress CGObjCGNU::GenerateConstantNumber(
const bool Value,
2747 const QualType &Ty) {
2748 llvm_unreachable(
"Method should not be called, no GNU runtimes provide these "
2749 "or support ObjC number literal constant initializers");
2752ConstantAddress CGObjCGNU::GenerateConstantNumber(
const llvm::APSInt &
Value,
2753 const QualType &Ty) {
2754 llvm_unreachable(
"Method should not be called, no GNU runtimes provide these "
2755 "or support ObjC number literal constant initializers");
2758ConstantAddress CGObjCGNU::GenerateConstantNumber(
const llvm::APFloat &
Value,
2759 const QualType &Ty) {
2760 llvm_unreachable(
"Method should not be called, no GNU runtimes provide these "
2761 "or support ObjC number literal constant initializers");
2765CGObjCGNU::GenerateConstantArray(
const ArrayRef<llvm::Constant *> &Objects) {
2766 llvm_unreachable(
"Method should not be called, no GNU runtimes provide these "
2767 "or support ObjC array literal constant initializers");
2770ConstantAddress CGObjCGNU::GenerateConstantDictionary(
2771 const ObjCDictionaryLiteral *E,
2772 ArrayRef<std::pair<llvm::Constant *, llvm::Constant *>> KeysAndObjects) {
2773 llvm_unreachable(
"Method should not be called, no GNU runtimes provide these "
2774 "or support ObjC dictionary literal constant initializers");
2781CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF,
2782 ReturnValueSlot Return,
2783 QualType ResultType,
2785 const ObjCInterfaceDecl *
Class,
2786 bool isCategoryImpl,
2787 llvm::Value *Receiver,
2788 bool IsClassMessage,
2789 const CallArgList &CallArgs,
2790 const ObjCMethodDecl *
Method) {
2791 CGBuilderTy &Builder = CGF.
Builder;
2792 if (CGM.
getLangOpts().getGC() == LangOptions::GCOnly) {
2793 if (Sel == RetainSel || Sel == AutoreleaseSel) {
2797 if (Sel == ReleaseSel) {
2802 llvm::Value *cmd = GetSelector(CGF, Sel);
2803 CallArgList ActualArgs;
2805 ActualArgs.
add(
RValue::get(EnforceType(Builder, Receiver, IdTy)), ASTIdTy);
2809 MessageSendInfo MSI = getMessageSendInfo(
Method, ResultType, ActualArgs);
2811 llvm::Value *ReceiverClass =
nullptr;
2814 ReceiverClass = GetClassNamed(CGF,
2815 Class->getSuperClass()->getNameAsString(),
false);
2816 if (IsClassMessage) {
2819 Builder.CreateAlignedLoad(IdTy, ReceiverClass, CGF.
getPointerAlign());
2821 ReceiverClass = EnforceType(Builder, ReceiverClass, IdTy);
2823 if (isCategoryImpl) {
2824 llvm::FunctionCallee classLookupFunction =
nullptr;
2825 if (IsClassMessage) {
2827 IdTy, PtrTy,
true),
"objc_get_meta_class");
2830 IdTy, PtrTy,
true),
"objc_get_class");
2832 ReceiverClass = Builder.CreateCall(classLookupFunction,
2833 MakeConstantString(
Class->getNameAsString()));
2840 if (IsClassMessage) {
2841 if (!MetaClassPtrAlias) {
2842 MetaClassPtrAlias = llvm::GlobalAlias::create(
2843 IdElemTy, 0, llvm::GlobalValue::InternalLinkage,
2844 ".objc_metaclass_ref" +
Class->getNameAsString(), &TheModule);
2846 ReceiverClass = MetaClassPtrAlias;
2848 if (!ClassPtrAlias) {
2849 ClassPtrAlias = llvm::GlobalAlias::create(
2850 IdElemTy, 0, llvm::GlobalValue::InternalLinkage,
2851 ".objc_class_ref" +
Class->getNameAsString(), &TheModule);
2853 ReceiverClass = ClassPtrAlias;
2857 llvm::Type *CastTy = llvm::StructType::get(IdTy, IdTy);
2859 ReceiverClass = Builder.CreateStructGEP(CastTy, ReceiverClass, 1);
2862 Builder.CreateAlignedLoad(IdTy, ReceiverClass, CGF.
getPointerAlign());
2865 llvm::StructType *ObjCSuperTy =
2866 llvm::StructType::get(Receiver->getType(), IdTy);
2871 Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0));
2872 Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1));
2875 llvm::Value *imp = LookupIMPSuper(CGF, ObjCSuper, cmd, MSI);
2876 imp = EnforceType(Builder, imp, MSI.MessengerType);
2878 llvm::Metadata *impMD[] = {
2879 llvm::MDString::get(VMContext, Sel.
getAsString()),
2880 llvm::MDString::get(VMContext,
Class->getSuperClass()->getNameAsString()),
2881 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2882 llvm::Type::getInt1Ty(VMContext), IsClassMessage))};
2883 llvm::MDNode *
node = llvm::MDNode::get(VMContext, impMD);
2885 CGCallee callee(CGCalleeInfo(), imp);
2887 llvm::CallBase *call;
2888 RValue msgRet = CGF.
EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
2889 call->setMetadata(msgSendMDKind, node);
2895CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
2896 ReturnValueSlot Return,
2897 QualType ResultType,
2899 llvm::Value *Receiver,
2900 const CallArgList &CallArgs,
2901 const ObjCInterfaceDecl *
Class,
2902 const ObjCMethodDecl *
Method) {
2903 CGBuilderTy &Builder = CGF.
Builder;
2906 if (CGM.
getLangOpts().getGC() == LangOptions::GCOnly) {
2907 if (Sel == RetainSel || Sel == AutoreleaseSel) {
2911 if (Sel == ReleaseSel) {
2922 cmd = GetSelector(CGF,
Method);
2924 cmd = GetSelector(CGF, Sel);
2925 cmd = EnforceType(Builder, cmd, SelectorTy);
2928 Receiver = EnforceType(Builder, Receiver, IdTy);
2930 llvm::Metadata *impMD[] = {
2931 llvm::MDString::get(VMContext, Sel.
getAsString()),
2932 llvm::MDString::get(VMContext,
Class ?
Class->getNameAsString() :
""),
2933 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2934 llvm::Type::getInt1Ty(VMContext),
Class !=
nullptr))};
2935 llvm::MDNode *
node = llvm::MDNode::get(VMContext, impMD);
2937 CallArgList ActualArgs;
2943 MessageSendInfo MSI = getMessageSendInfo(
Method, ResultType, ActualArgs);
2964 bool hasParamDestroyedInCallee =
false;
2965 bool requiresExplicitZeroResult =
false;
2966 bool requiresNilReceiverCheck = [&] {
2968 if (!canMessageReceiverBeNull(CGF,
Method,
false,
2974 hasParamDestroyedInCallee =
true;
2995 requiresExplicitZeroResult = !isDirect;
2999 return hasParamDestroyedInCallee || requiresExplicitZeroResult;
3005 bool requiresExplicitAggZeroing =
3009 llvm::BasicBlock *continueBB =
nullptr;
3011 llvm::BasicBlock *nilPathBB =
nullptr;
3013 llvm::BasicBlock *nilCleanupBB =
nullptr;
3016 if (requiresNilReceiverCheck) {
3023 if (requiresExplicitAggZeroing || hasParamDestroyedInCallee) {
3026 nilPathBB = Builder.GetInsertBlock();
3029 llvm::Value *isNil = Builder.CreateICmpEQ(Receiver,
3030 llvm::Constant::getNullValue(Receiver->getType()));
3031 Builder.CreateCondBr(isNil, nilCleanupBB ? nilCleanupBB : continueBB,
3041 imp = GenerateMethod(
Method,
Method->getClassInterface());
3048 imp = LookupIMP(CGF, Receiver, cmd, node, MSI);
3052 StringRef
name =
"objc_msgSend";
3054 name =
"objc_msgSend_fpret";
3056 name =
"objc_msgSend_stret";
3060 bool shouldCheckForInReg =
3064 .isWindowsMSVCEnvironment() &&
3067 name =
"objc_msgSend_stret2";
3078 ActualArgs[0] = CallArg(
RValue::get(Receiver), ASTIdTy);
3080 imp = EnforceType(Builder, imp, MSI.MessengerType);
3082 llvm::CallBase *call;
3083 CGCallee callee(CGCalleeInfo(), imp);
3084 RValue msgRet = CGF.
EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
3086 call->setMetadata(msgSendMDKind, node);
3088 if (requiresNilReceiverCheck) {
3089 llvm::BasicBlock *nonNilPathBB = CGF.
Builder.GetInsertBlock();
3090 CGF.
Builder.CreateBr(continueBB);
3096 if (hasParamDestroyedInCallee) {
3097 destroyCalleeDestroyedArguments(CGF,
Method, CallArgs);
3100 if (requiresExplicitAggZeroing) {
3106 nilPathBB = CGF.
Builder.GetInsertBlock();
3107 CGF.
Builder.CreateBr(continueBB);
3115 llvm::PHINode *phi = Builder.CreatePHI(v->getType(), 2);
3116 phi->addIncoming(v, nonNilPathBB);
3123 std::pair<llvm::Value*,llvm::Value*> v = msgRet.
getComplexVal();
3124 llvm::PHINode *phi = Builder.CreatePHI(v.first->getType(), 2);
3125 phi->addIncoming(v.first, nonNilPathBB);
3126 phi->addIncoming(llvm::Constant::getNullValue(v.first->getType()),
3128 llvm::PHINode *phi2 = Builder.CreatePHI(v.second->getType(), 2);
3129 phi2->addIncoming(v.second, nonNilPathBB);
3130 phi2->addIncoming(llvm::Constant::getNullValue(v.second->getType()),
3140llvm::Constant *CGObjCGNU::
3141GenerateMethodList(StringRef ClassName,
3142 StringRef CategoryName,
3143 ArrayRef<const ObjCMethodDecl*> Methods,
3144 bool isClassMethodList) {
3145 if (Methods.empty())
3148 ConstantInitBuilder Builder(CGM);
3150 auto MethodList = Builder.beginStruct();
3151 MethodList.addNullPointer(CGM.
Int8PtrTy);
3152 MethodList.addInt(Int32Ty, Methods.size());
3155 llvm::StructType *ObjCMethodTy =
3164 const llvm::DataLayout &DL = TheModule.getDataLayout();
3165 MethodList.addInt(SizeTy, DL.getTypeSizeInBits(ObjCMethodTy) /
3181 auto MethodArray = MethodList.beginArray();
3183 for (
const auto *OMD : Methods) {
3184 llvm::Constant *FnPtr =
3185 TheModule.getFunction(getSymbolNameForMethod(OMD));
3186 assert(FnPtr &&
"Can't generate metadata for method that doesn't exist");
3187 auto Method = MethodArray.beginStruct(ObjCMethodTy);
3198 Method.finishAndAddTo(MethodArray);
3200 MethodArray.finishAndAddTo(MethodList);
3203 return MethodList.finishAndCreateGlobal(
".objc_method_list",
3208llvm::Constant *CGObjCGNU::
3209GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
3210 ArrayRef<llvm::Constant *> IvarTypes,
3211 ArrayRef<llvm::Constant *> IvarOffsets,
3212 ArrayRef<llvm::Constant *> IvarAlign,
3213 ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership) {
3214 if (IvarNames.empty())
3217 ConstantInitBuilder Builder(CGM);
3220 auto IvarList = Builder.beginStruct();
3221 IvarList.addInt(IntTy, (
int)IvarNames.size());
3224 llvm::StructType *ObjCIvarTy =
3225 llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy);
3228 auto Ivars = IvarList.beginArray(ObjCIvarTy);
3229 for (
unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
3230 auto Ivar = Ivars.beginStruct(ObjCIvarTy);
3231 Ivar.
add(IvarNames[i]);
3232 Ivar.
add(IvarTypes[i]);
3233 Ivar.
add(IvarOffsets[i]);
3234 Ivar.finishAndAddTo(Ivars);
3236 Ivars.finishAndAddTo(IvarList);
3239 return IvarList.finishAndCreateGlobal(
".objc_ivar_list",
3244llvm::Constant *CGObjCGNU::GenerateClassStructure(
3245 llvm::Constant *MetaClass,
3246 llvm::Constant *SuperClass,
3249 llvm::Constant *Version,
3250 llvm::Constant *InstanceSize,
3251 llvm::Constant *IVars,
3252 llvm::Constant *Methods,
3253 llvm::Constant *Protocols,
3254 llvm::Constant *IvarOffsets,
3255 llvm::Constant *Properties,
3256 llvm::Constant *StrongIvarBitmap,
3257 llvm::Constant *WeakIvarBitmap,
3266 llvm::StructType *ClassTy = llvm::StructType::get(
3283 IvarOffsets->getType(),
3284 Properties->getType(),
3289 ConstantInitBuilder Builder(CGM);
3290 auto Elements = Builder.beginStruct(ClassTy);
3295 Elements.add(MetaClass);
3297 Elements.add(SuperClass);
3299 Elements.add(MakeConstantString(Name,
".class_name"));
3301 Elements.addInt(LongTy, 0);
3303 Elements.addInt(LongTy, info);
3306 const llvm::DataLayout &DL = TheModule.getDataLayout();
3307 Elements.addInt(LongTy, DL.getTypeSizeInBits(ClassTy) /
3310 Elements.add(InstanceSize);
3312 Elements.add(IVars);
3314 Elements.add(Methods);
3317 Elements.add(NULLPtr);
3319 Elements.add(NULLPtr);
3321 Elements.add(NULLPtr);
3323 Elements.add(Protocols);
3325 Elements.add(NULLPtr);
3327 Elements.addInt(LongTy, ClassABIVersion);
3329 Elements.add(IvarOffsets);
3331 Elements.add(Properties);
3333 Elements.add(StrongIvarBitmap);
3335 Elements.add(WeakIvarBitmap);
3340 std::string ClassSym((isMeta ?
"_OBJC_METACLASS_":
"_OBJC_CLASS_") +
3342 llvm::GlobalVariable *ClassRef = TheModule.getNamedGlobal(ClassSym);
3343 llvm::Constant *
Class =
3344 Elements.finishAndCreateGlobal(ClassSym, CGM.
getPointerAlign(),
false,
3345 llvm::GlobalValue::ExternalLinkage);
3347 ClassRef->replaceAllUsesWith(
Class);
3348 ClassRef->removeFromParent();
3349 Class->setName(ClassSym);
3354llvm::Constant *CGObjCGNU::
3355GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods) {
3357 llvm::StructType *ObjCMethodDescTy =
3358 llvm::StructType::get(CGM.
getLLVMContext(), { PtrToInt8Ty, PtrToInt8Ty });
3360 ConstantInitBuilder Builder(CGM);
3361 auto MethodList = Builder.beginStruct();
3362 MethodList.addInt(IntTy, Methods.size());
3363 auto MethodArray = MethodList.beginArray(ObjCMethodDescTy);
3364 for (
auto *M : Methods) {
3365 auto Method = MethodArray.beginStruct(ObjCMethodDescTy);
3366 Method.add(MakeConstantString(M->getSelector().getAsString()));
3368 Method.finishAndAddTo(MethodArray);
3370 MethodArray.finishAndAddTo(MethodList);
3371 return MethodList.finishAndCreateGlobal(
".objc_method_list",
3377CGObjCGNU::GenerateProtocolList(ArrayRef<std::string> Protocols) {
3379 ConstantInitBuilder Builder(CGM);
3380 auto ProtocolList = Builder.beginStruct();
3381 ProtocolList.add(NULLPtr);
3382 ProtocolList.addInt(LongTy, Protocols.size());
3384 auto Elements = ProtocolList.beginArray(PtrToInt8Ty);
3385 for (
const std::string &Protocol : Protocols) {
3386 llvm::Constant *protocol =
nullptr;
3387 llvm::StringMap<llvm::Constant *>::iterator value =
3388 ExistingProtocols.find(Protocol);
3389 if (value == ExistingProtocols.end()) {
3390 protocol = GenerateEmptyProtocol(Protocol);
3392 protocol = value->getValue();
3394 Elements.add(protocol);
3396 Elements.finishAndAddTo(ProtocolList);
3397 return ProtocolList.finishAndCreateGlobal(
".objc_protocol_list",
3401llvm::Value *CGObjCGNU::GenerateProtocolRef(CodeGenFunction &CGF,
3402 const ObjCProtocolDecl *PD) {
3403 return GenerateProtocolRef(PD);
3406llvm::Constant *CGObjCGNU::GenerateProtocolRef(
const ObjCProtocolDecl *PD) {
3409 GenerateProtocol(PD);
3410 assert(protocol &&
"Unknown protocol");
3415CGObjCGNU::GenerateEmptyProtocol(StringRef ProtocolName) {
3416 llvm::Constant *ProtocolList = GenerateProtocolList({});
3417 llvm::Constant *MethodList = GenerateProtocolMethodList({});
3420 ConstantInitBuilder Builder(CGM);
3421 auto Elements = Builder.beginStruct();
3425 Elements.add(llvm::ConstantExpr::getIntToPtr(
3426 llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
3428 Elements.add(MakeConstantString(ProtocolName,
".objc_protocol_name"));
3429 Elements.add(ProtocolList);
3430 Elements.add(MethodList);
3431 Elements.add(MethodList);
3432 Elements.add(MethodList);
3433 Elements.add(MethodList);
3434 Elements.add(NULLPtr);
3435 Elements.add(NULLPtr);
3436 return Elements.finishAndCreateGlobal(SymbolForProtocol(ProtocolName),
3440void CGObjCGNU::GenerateProtocol(
const ObjCProtocolDecl *PD) {
3450 SmallVector<std::string, 16> Protocols;
3452 Protocols.push_back(PI->getNameAsString());
3453 SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
3454 SmallVector<const ObjCMethodDecl*, 16> OptionalInstanceMethods;
3456 if (I->isOptional())
3457 OptionalInstanceMethods.push_back(I);
3459 InstanceMethods.push_back(I);
3461 SmallVector<const ObjCMethodDecl*, 16> ClassMethods;
3462 SmallVector<const ObjCMethodDecl*, 16> OptionalClassMethods;
3464 if (I->isOptional())
3465 OptionalClassMethods.push_back(I);
3467 ClassMethods.push_back(I);
3469 llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
3470 llvm::Constant *InstanceMethodList =
3471 GenerateProtocolMethodList(InstanceMethods);
3472 llvm::Constant *ClassMethodList =
3473 GenerateProtocolMethodList(ClassMethods);
3474 llvm::Constant *OptionalInstanceMethodList =
3475 GenerateProtocolMethodList(OptionalInstanceMethods);
3476 llvm::Constant *OptionalClassMethodList =
3477 GenerateProtocolMethodList(OptionalClassMethods);
3485 llvm::Constant *PropertyList =
3486 GeneratePropertyList(
nullptr, PD,
false,
false);
3487 llvm::Constant *OptionalPropertyList =
3488 GeneratePropertyList(
nullptr, PD,
false,
true);
3494 ConstantInitBuilder Builder(CGM);
3495 auto Elements = Builder.beginStruct();
3497 llvm::ConstantExpr::getIntToPtr(
3498 llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
3499 Elements.add(MakeConstantString(ProtocolName));
3500 Elements.add(ProtocolList);
3501 Elements.add(InstanceMethodList);
3502 Elements.add(ClassMethodList);
3503 Elements.add(OptionalInstanceMethodList);
3504 Elements.add(OptionalClassMethodList);
3505 Elements.add(PropertyList);
3506 Elements.add(OptionalPropertyList);
3507 ExistingProtocols[ProtocolName] =
3508 Elements.finishAndCreateGlobal(
".objc_protocol", CGM.
getPointerAlign());
3510void CGObjCGNU::GenerateProtocolHolderCategory() {
3513 ConstantInitBuilder Builder(CGM);
3514 auto Elements = Builder.beginStruct();
3516 const std::string ClassName =
"__ObjC_Protocol_Holder_Ugly_Hack";
3517 const std::string CategoryName =
"AnotherHack";
3518 Elements.add(MakeConstantString(CategoryName));
3519 Elements.add(MakeConstantString(ClassName));
3521 Elements.add(GenerateMethodList(ClassName, CategoryName, {},
false));
3523 Elements.add(GenerateMethodList(ClassName, CategoryName, {},
true));
3526 ConstantInitBuilder ProtocolListBuilder(CGM);
3527 auto ProtocolList = ProtocolListBuilder.beginStruct();
3528 ProtocolList.add(NULLPtr);
3529 ProtocolList.addInt(LongTy, ExistingProtocols.size());
3530 auto ProtocolElements = ProtocolList.beginArray(PtrTy);
3531 for (
auto iter = ExistingProtocols.begin(), endIter = ExistingProtocols.end();
3532 iter != endIter ; iter++) {
3533 ProtocolElements.add(iter->getValue());
3535 ProtocolElements.finishAndAddTo(ProtocolList);
3536 Elements.add(ProtocolList.finishAndCreateGlobal(
".objc_protocol_list",
3538 Categories.push_back(
3553llvm::Constant *CGObjCGNU::MakeBitField(ArrayRef<bool> bits) {
3554 int bitCount = bits.size();
3556 if (bitCount < ptrBits) {
3558 for (
int i=0 ; i<bitCount ; ++i) {
3559 if (bits[i]) val |= 1ULL<<(i+1);
3561 return llvm::ConstantInt::get(IntPtrTy, val);
3563 SmallVector<llvm::Constant *, 8> values;
3565 while (v < bitCount) {
3567 for (
int i=0 ; (i<32) && (v<bitCount) ; ++i) {
3568 if (bits[v]) word |= 1<<i;
3571 values.push_back(llvm::ConstantInt::get(Int32Ty, word));
3574 ConstantInitBuilder builder(CGM);
3575 auto fields = builder.beginStruct();
3576 fields.addInt(Int32Ty, values.size());
3577 auto array = fields.beginArray();
3578 for (
auto *v : values) array.add(v);
3579 array.finishAndAddTo(fields);
3581 llvm::Constant *GS =
3583 llvm::Constant *ptr = llvm::ConstantExpr::getPtrToInt(GS, IntPtrTy);
3587llvm::Constant *CGObjCGNU::GenerateCategoryProtocolList(
const
3588 ObjCCategoryDecl *OCD) {
3590 const auto RuntimeProtos =
3591 GetRuntimeProtocolList(RefPro.begin(), RefPro.end());
3592 SmallVector<std::string, 16> Protocols;
3593 for (
const auto *PD : RuntimeProtos)
3595 return GenerateProtocolList(Protocols);
3598void CGObjCGNU::GenerateCategory(
const ObjCCategoryImplDecl *OCD) {
3600 std::string ClassName =
Class->getNameAsString();
3606 ConstantInitBuilder Builder(CGM);
3607 auto Elements = Builder.beginStruct();
3608 Elements.add(MakeConstantString(CategoryName));
3609 Elements.add(MakeConstantString(ClassName));
3611 SmallVector<ObjCMethodDecl*, 16> InstanceMethods;
3612 InstanceMethods.insert(InstanceMethods.begin(), OCD->
instmeth_begin(),
3615 GenerateMethodList(ClassName, CategoryName, InstanceMethods,
false));
3619 SmallVector<ObjCMethodDecl*, 16> ClassMethods;
3622 Elements.add(GenerateMethodList(ClassName, CategoryName, ClassMethods,
true));
3625 Elements.add(GenerateCategoryProtocolList(CatDecl));
3627 const ObjCCategoryDecl *Category =
3631 Elements.add(GeneratePropertyList(OCD, Category,
false));
3633 Elements.add(GeneratePropertyList(OCD, Category,
true));
3635 Elements.addNullPointer(PtrTy);
3636 Elements.addNullPointer(PtrTy);
3640 Categories.push_back(Elements.finishAndCreateGlobal(
3641 std::string(
".objc_category_") + ClassName + CategoryName,
3645llvm::Constant *CGObjCGNU::GeneratePropertyList(
const Decl *Container,
3646 const ObjCContainerDecl *OCD,
3647 bool isClassProperty,
3648 bool protocolOptionalProperties) {
3650 SmallVector<const ObjCPropertyDecl *, 16> Properties;
3651 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
3655 std::function<void(
const ObjCProtocolDecl *Proto)> collectProtocolProperties
3656 = [&](
const ObjCProtocolDecl *Proto) {
3657 for (
const auto *P : Proto->protocols())
3658 collectProtocolProperties(P);
3659 for (
const auto *PD : Proto->properties()) {
3660 if (isClassProperty != PD->isClassProperty())
3668 Properties.push_back(PD);
3672 if (
const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
3674 for (
auto *PD : ClassExt->properties()) {
3675 if (isClassProperty != PD->isClassProperty())
3678 Properties.push_back(PD);
3682 if (isClassProperty != PD->isClassProperty())
3686 if (isProtocol && (protocolOptionalProperties != PD->isOptional()))
3693 Properties.push_back(PD);
3696 if (
const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
3698 collectProtocolProperties(P);
3699 else if (
const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD))
3700 for (
const auto *P : CD->protocols())
3701 collectProtocolProperties(P);
3703 auto numProperties = Properties.size();
3705 if (numProperties == 0)
3708 ConstantInitBuilder builder(CGM);
3709 auto propertyList = builder.beginStruct();
3710 auto properties = PushPropertyListHeader(propertyList, numProperties);
3714 for (
auto *property : Properties) {
3715 bool isSynthesized =
false;
3716 bool isDynamic =
false;
3720 isSynthesized = (propertyImpl->getPropertyImplementation() ==
3722 isDynamic = (propertyImpl->getPropertyImplementation() ==
3726 PushProperty(properties, property, Container, isSynthesized, isDynamic);
3728 properties.finishAndAddTo(propertyList);
3730 return propertyList.finishAndCreateGlobal(
".objc_property_list",
3734void CGObjCGNU::RegisterAlias(
const ObjCCompatibleAliasDecl *OAD) {
3736 ObjCInterfaceDecl *ClassDecl =
3742void CGObjCGNU::GenerateClass(
const ObjCImplementationDecl *OID) {
3746 const ObjCInterfaceDecl * SuperClassDecl =
3748 std::string SuperClassName;
3749 if (SuperClassDecl) {
3751 EmitClassRef(SuperClassName);
3755 ObjCInterfaceDecl *ClassDecl =
3761 std::string classSymbolName =
"__objc_class_name_" + ClassName;
3762 if (
auto *symbol = TheModule.getGlobalVariable(classSymbolName)) {
3763 symbol->setInitializer(llvm::ConstantInt::get(LongTy, 0));
3765 new llvm::GlobalVariable(TheModule, LongTy,
false,
3766 llvm::GlobalValue::ExternalLinkage,
3767 llvm::ConstantInt::get(LongTy, 0),
3777 SmallVector<llvm::Constant*, 16> IvarNames;
3778 SmallVector<llvm::Constant*, 16> IvarTypes;
3779 SmallVector<llvm::Constant*, 16> IvarOffsets;
3780 SmallVector<llvm::Constant*, 16> IvarAligns;
3781 SmallVector<Qualifiers::ObjCLifetime, 16> IvarOwnership;
3783 ConstantInitBuilder IvarOffsetBuilder(CGM);
3784 auto IvarOffsetValues = IvarOffsetBuilder.beginArray(PtrToIntTy);
3785 SmallVector<bool, 16> WeakIvars;
3786 SmallVector<bool, 16> StrongIvars;
3788 int superInstanceSize = !SuperClassDecl ? 0 :
3793 instanceSize = 0 - (instanceSize - superInstanceSize);
3799 IvarNames.push_back(MakeConstantString(IVD->getNameAsString()));
3801 std::string TypeStr;
3803 IvarTypes.push_back(MakeConstantString(TypeStr));
3804 IvarAligns.push_back(llvm::ConstantInt::get(IntTy,
3807 uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
3810 Offset =
static_cast<int64_t>(BaseOffset) - superInstanceSize;
3812 llvm::Constant *OffsetValue = llvm::ConstantInt::getSigned(IntTy, Offset);
3814 std::string OffsetName =
"__objc_ivar_offset_value_" + ClassName +
"." +
3815 IVD->getNameAsString();
3817 llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName);
3819 OffsetVar->setInitializer(OffsetValue);
3823 OffsetVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
3825 OffsetVar =
new llvm::GlobalVariable(TheModule, Int32Ty,
3826 false, llvm::GlobalValue::ExternalLinkage,
3827 OffsetValue, OffsetName);
3828 IvarOffsets.push_back(OffsetValue);
3829 IvarOffsetValues.add(OffsetVar);
3831 IvarOwnership.push_back(lt);
3834 StrongIvars.push_back(
true);
3835 WeakIvars.push_back(
false);
3838 StrongIvars.push_back(
false);
3839 WeakIvars.push_back(
true);
3842 StrongIvars.push_back(
false);
3843 WeakIvars.push_back(
false);
3846 llvm::Constant *StrongIvarBitmap = MakeBitField(StrongIvars);
3847 llvm::Constant *WeakIvarBitmap = MakeBitField(WeakIvars);
3848 llvm::GlobalVariable *IvarOffsetArray =
3849 IvarOffsetValues.finishAndCreateGlobal(
".ivar.offsets",
3853 SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
3854 InstanceMethods.insert(InstanceMethods.begin(), OID->
instmeth_begin(),
3857 SmallVector<const ObjCMethodDecl*, 16> ClassMethods;
3861 llvm::Constant *Properties = GeneratePropertyList(OID, ClassDecl);
3864 auto RefProtocols = ClassDecl->
protocols();
3865 auto RuntimeProtocols =
3866 GetRuntimeProtocolList(RefProtocols.begin(), RefProtocols.end());
3867 SmallVector<std::string, 16> Protocols;
3868 for (
const auto *I : RuntimeProtocols)
3869 Protocols.push_back(I->getNameAsString());
3872 llvm::Constant *SuperClass;
3873 if (!SuperClassName.empty()) {
3874 SuperClass = MakeConstantString(SuperClassName,
".super_class_name");
3876 SuperClass = llvm::ConstantPointerNull::get(PtrToInt8Ty);
3879 llvm::Constant *MethodList = GenerateMethodList(ClassName,
"",
3880 InstanceMethods,
false);
3881 llvm::Constant *ClassMethodList = GenerateMethodList(ClassName,
"",
3882 ClassMethods,
true);
3883 llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
3884 IvarOffsets, IvarAligns, IvarOwnership);
3895 llvm::Type *IndexTy = Int32Ty;
3896 llvm::Constant *offsetPointerIndexes[] = {Zeros[0],
3897 llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 2 : 1),
nullptr,
3898 llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 3 : 2) };
3900 unsigned ivarIndex = 0;
3903 const std::string Name = GetIVarOffsetVariableName(ClassDecl, IVD);
3904 offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, ivarIndex);
3906 llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr(
3908 offsetPointerIndexes);
3910 llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name);
3912 offset->setInitializer(offsetValue);
3916 offset->setLinkage(llvm::GlobalValue::ExternalLinkage);
3919 new llvm::GlobalVariable(TheModule, offsetValue->getType(),
3920 false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name);
3923 llvm::Constant *ZeroPtr = llvm::ConstantInt::get(IntPtrTy, 0);
3926 llvm::Constant *MetaClassStruct = GenerateClassStructure(
3927 NULLPtr, NULLPtr, 0x12L, ClassName.c_str(),
nullptr, Zeros[0],
3928 NULLPtr, ClassMethodList, NULLPtr, NULLPtr,
3929 GeneratePropertyList(OID, ClassDecl,
true), ZeroPtr, ZeroPtr,
true);
3934 llvm::Constant *ClassStruct = GenerateClassStructure(
3935 MetaClassStruct, SuperClass, 0x11L, ClassName.c_str(),
nullptr,
3936 llvm::ConstantInt::getSigned(LongTy, instanceSize), IvarList, MethodList,
3937 GenerateProtocolList(Protocols), IvarOffsetArray, Properties,
3938 StrongIvarBitmap, WeakIvarBitmap);
3943 if (ClassPtrAlias) {
3944 ClassPtrAlias->replaceAllUsesWith(ClassStruct);
3945 ClassPtrAlias->eraseFromParent();
3946 ClassPtrAlias =
nullptr;
3948 if (MetaClassPtrAlias) {
3949 MetaClassPtrAlias->replaceAllUsesWith(MetaClassStruct);
3950 MetaClassPtrAlias->eraseFromParent();
3951 MetaClassPtrAlias =
nullptr;
3955 Classes.push_back(ClassStruct);
3958llvm::Function *CGObjCGNU::ModuleInitFunction() {
3960 if (Classes.empty() && Categories.empty() && ConstantStrings.empty() &&
3961 ExistingProtocols.empty() && SelectorTable.empty())
3965 GenerateProtocolHolderCategory();
3967 llvm::StructType *selStructTy = dyn_cast<llvm::StructType>(SelectorElemTy);
3970 { PtrToInt8Ty, PtrToInt8Ty });
3974 llvm::Constant *statics = NULLPtr;
3975 if (!ConstantStrings.empty()) {
3976 llvm::GlobalVariable *fileStatics = [&] {
3977 ConstantInitBuilder builder(CGM);
3978 auto staticsStruct = builder.beginStruct();
3981 if (stringClass.empty()) stringClass =
"NXConstantString";
3982 staticsStruct.add(MakeConstantString(stringClass,
3983 ".objc_static_class_name"));
3985 auto array = staticsStruct.beginArray();
3986 array.addAll(ConstantStrings);
3988 array.finishAndAddTo(staticsStruct);
3990 return staticsStruct.finishAndCreateGlobal(
".objc_statics",
3994 ConstantInitBuilder builder(CGM);
3995 auto allStaticsArray = builder.beginArray(fileStatics->getType());
3996 allStaticsArray.add(fileStatics);
3997 allStaticsArray.addNullPointer(fileStatics->getType());
3999 statics = allStaticsArray.finishAndCreateGlobal(
".objc_statics_ptr",
4005 SmallVector<llvm::GlobalAlias*, 16> selectorAliases;
4006 unsigned selectorCount;
4009 llvm::GlobalVariable *selectorList = [&] {
4010 ConstantInitBuilder builder(CGM);
4011 auto selectors = builder.beginArray(selStructTy);
4012 auto &table = SelectorTable;
4013 std::vector<Selector> allSelectors;
4014 for (
auto &entry : table)
4015 allSelectors.push_back(entry.first);
4016 llvm::sort(allSelectors);
4018 for (
auto &untypedSel : allSelectors) {
4019 std::string selNameStr = untypedSel.getAsString();
4020 llvm::Constant *selName = ExportUniqueString(selNameStr,
".objc_sel_name");
4022 for (TypedSelector &sel : table[untypedSel]) {
4023 llvm::Constant *selectorTypeEncoding = NULLPtr;
4024 if (!sel.first.empty())
4025 selectorTypeEncoding =
4026 MakeConstantString(sel.first,
".objc_sel_types");
4028 auto selStruct = selectors.beginStruct(selStructTy);
4029 selStruct.add(selName);
4030 selStruct.add(selectorTypeEncoding);
4031 selStruct.finishAndAddTo(selectors);
4034 selectorAliases.push_back(sel.second);
4039 selectorCount = selectors.size();
4045 auto selStruct = selectors.beginStruct(selStructTy);
4046 selStruct.add(NULLPtr);
4047 selStruct.add(NULLPtr);
4048 selStruct.finishAndAddTo(selectors);
4050 return selectors.finishAndCreateGlobal(
".objc_selector_list",
4055 for (
unsigned i = 0; i < selectorCount; ++i) {
4056 llvm::Constant *idxs[] = {
4058 llvm::ConstantInt::get(Int32Ty, i)
4061 llvm::Constant *selPtr = llvm::ConstantExpr::getGetElementPtr(
4062 selectorList->getValueType(), selectorList, idxs);
4063 selectorAliases[i]->replaceAllUsesWith(selPtr);
4064 selectorAliases[i]->eraseFromParent();
4067 llvm::GlobalVariable *symtab = [&] {
4068 ConstantInitBuilder builder(CGM);
4069 auto symtab = builder.beginStruct();
4072 symtab.addInt(LongTy, selectorCount);
4074 symtab.add(selectorList);
4077 symtab.addInt(CGM.
Int16Ty, Classes.size());
4079 symtab.addInt(CGM.
Int16Ty, Categories.size());
4082 auto classList = symtab.beginArray(PtrToInt8Ty);
4083 classList.addAll(Classes);
4084 classList.addAll(Categories);
4086 classList.add(statics);
4087 classList.add(NULLPtr);
4088 classList.finishAndAddTo(symtab);
4096 llvm::Constant *module = [&] {
4097 llvm::Type *moduleEltTys[] = {
4098 LongTy, LongTy, PtrToInt8Ty, symtab->getType(), IntTy
4100 llvm::StructType *moduleTy = llvm::StructType::get(
4102 ArrayRef(moduleEltTys).drop_back(
unsigned(RuntimeVersion < 10)));
4104 ConstantInitBuilder builder(CGM);
4105 auto module = builder.beginStruct(moduleTy);
4107 module.addInt(LongTy, RuntimeVersion);
4109 module.addInt(LongTy, CGM.getDataLayout().getTypeStoreSize(moduleTy));
4116 module.add(MakeConstantString(path, ".objc_source_file_name"));
4119 if (RuntimeVersion >= 10) {
4121 case LangOptions::GCOnly:
4122 module.addInt(IntTy, 2);
4124 case LangOptions::NonGC:
4126 module.addInt(IntTy, 1);
4128 module.addInt(IntTy, 0);
4130 case LangOptions::HybridGC:
4131 module.addInt(IntTy, 1);
4136 return module.finishAndCreateGlobal("", CGM.getPointerAlign());
4141 llvm::Function * LoadFunction = llvm::Function::Create(
4142 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
false),
4143 llvm::GlobalValue::InternalLinkage,
".objc_load_function",
4145 llvm::BasicBlock *EntryBB =
4146 llvm::BasicBlock::Create(VMContext,
"entry", LoadFunction);
4147 CGBuilderTy Builder(CGM, VMContext);
4148 Builder.SetInsertPoint(EntryBB);
4150 llvm::FunctionType *FT =
4151 llvm::FunctionType::get(Builder.getVoidTy(), module->getType(),
true);
4152 llvm::FunctionCallee Register =
4154 Builder.CreateCall(Register, module);
4156 if (!ClassAliases.empty()) {
4157 llvm::Type *ArgTypes[2] = {PtrTy, PtrToInt8Ty};
4158 llvm::FunctionType *RegisterAliasTy =
4159 llvm::FunctionType::get(Builder.getVoidTy(),
4161 llvm::Function *RegisterAlias = llvm::Function::Create(
4163 llvm::GlobalValue::ExternalWeakLinkage,
"class_registerAlias_np",
4165 llvm::BasicBlock *AliasBB =
4166 llvm::BasicBlock::Create(VMContext,
"alias", LoadFunction);
4167 llvm::BasicBlock *NoAliasBB =
4168 llvm::BasicBlock::Create(VMContext,
"no_alias", LoadFunction);
4171 llvm::Value *HasRegisterAlias = Builder.CreateICmpNE(RegisterAlias,
4172 llvm::Constant::getNullValue(RegisterAlias->getType()));
4173 Builder.CreateCondBr(HasRegisterAlias, AliasBB, NoAliasBB);
4176 Builder.SetInsertPoint(AliasBB);
4178 for (std::vector<ClassAliasPair>::iterator iter = ClassAliases.begin();
4179 iter != ClassAliases.end(); ++iter) {
4180 llvm::Constant *TheClass =
4181 TheModule.getGlobalVariable(
"_OBJC_CLASS_" + iter->first,
true);
4183 Builder.CreateCall(RegisterAlias,
4184 {TheClass, MakeConstantString(iter->second)});
4188 Builder.CreateBr(NoAliasBB);
4191 Builder.SetInsertPoint(NoAliasBB);
4193 Builder.CreateRetVoid();
4195 return LoadFunction;
4198llvm::Function *CGObjCGNU::GenerateMethod(
const ObjCMethodDecl *OMD,
4199 const ObjCContainerDecl *CD) {
4200 CodeGenTypes &Types = CGM.
getTypes();
4201 llvm::FunctionType *MethodTy =
4205 std::string FunctionName =
4206 getSymbolNameForMethod(OMD, !isDirect);
4209 return llvm::Function::Create(MethodTy,
4210 llvm::GlobalVariable::InternalLinkage,
4211 FunctionName, &TheModule);
4214 auto I = DirectMethodDefinitions.find(COMD);
4215 llvm::Function *OldFn =
nullptr, *
Fn =
nullptr;
4217 if (I == DirectMethodDefinitions.end()) {
4219 llvm::Function::Create(MethodTy, llvm::GlobalVariable::ExternalLinkage,
4220 FunctionName, &TheModule);
4221 DirectMethodDefinitions.insert(std::make_pair(COMD, F));
4238 Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
"",
4240 Fn->takeName(OldFn);
4241 OldFn->replaceAllUsesWith(Fn);
4242 OldFn->eraseFromParent();
4249void CGObjCGNU::GenerateDirectMethodsPreconditionCheck(
4250 CodeGenFunction &CGF, llvm::Function *Fn,
const ObjCMethodDecl *OMD,
4251 const ObjCContainerDecl *CD) {
4253 "Direct method precondition checks not supported in GNU runtime yet");
4256void CGObjCGNU::GenerateDirectMethodPrologue(CodeGenFunction &CGF,
4258 const ObjCMethodDecl *OMD,
4259 const ObjCContainerDecl *CD) {
4261 "Direct method precondition checks not supported in GNU runtime yet");
4264llvm::FunctionCallee CGObjCGNU::GetPropertyGetFunction() {
4265 return GetPropertyFn;
4268llvm::FunctionCallee CGObjCGNU::GetPropertySetFunction() {
4269 return SetPropertyFn;
4272llvm::FunctionCallee CGObjCGNU::GetOptimizedPropertySetFunction(
bool atomic,
4277llvm::FunctionCallee CGObjCGNU::GetGetStructFunction() {
4278 return GetStructPropertyFn;
4281llvm::FunctionCallee CGObjCGNU::GetSetStructFunction() {
4282 return SetStructPropertyFn;
4285llvm::FunctionCallee CGObjCGNU::GetCppAtomicObjectGetFunction() {
4289llvm::FunctionCallee CGObjCGNU::GetCppAtomicObjectSetFunction() {
4293llvm::FunctionCallee CGObjCGNU::EnumerationMutationFunction() {
4294 return EnumerationMutationFn;
4297void CGObjCGNU::EmitSynchronizedStmt(CodeGenFunction &CGF,
4298 const ObjCAtSynchronizedStmt &S) {
4299 EmitAtSynchronizedStmt(CGF, S, SyncEnterFn, SyncExitFn);
4303void CGObjCGNU::EmitTryStmt(CodeGenFunction &CGF,
4304 const ObjCAtTryStmt &S) {
4316 EmitTryCatchStmt(CGF, S, EnterCatchFn, ExitCatchFn, ExceptionReThrowFn);
4319void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
4320 const ObjCAtThrowStmt &S,
4321 bool ClearInsertionPoint) {
4322 llvm::Value *ExceptionAsObject;
4323 bool isRethrow =
false;
4327 ExceptionAsObject = Exception;
4330 "Unexpected rethrow outside @catch block.");
4334 if (isRethrow && (usesSEHExceptions || usesCxxExceptions)) {
4343 Throw->setDoesNotReturn();
4345 ExceptionAsObject = CGF.
Builder.CreateBitCast(ExceptionAsObject, IdTy);
4346 llvm::CallBase *Throw =
4348 Throw->setDoesNotReturn();
4350 CGF.
Builder.CreateUnreachable();
4351 if (ClearInsertionPoint)
4352 CGF.
Builder.ClearInsertionPoint();
4355llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGenFunction &CGF,
4356 Address AddrWeakObj) {
4358 return B.CreateCall(
4359 WeakReadFn, EnforceType(B, AddrWeakObj.
emitRawPointer(CGF), PtrToIdTy));
4362void CGObjCGNU::EmitObjCWeakAssign(CodeGenFunction &CGF,
4363 llvm::Value *src, Address dst) {
4365 src = EnforceType(B, src, IdTy);
4366 llvm::Value *dstVal = EnforceType(B, dst.
emitRawPointer(CGF), PtrToIdTy);
4367 B.CreateCall(WeakAssignFn, {src, dstVal});
4370void CGObjCGNU::EmitObjCGlobalAssign(CodeGenFunction &CGF,
4371 llvm::Value *src, Address dst,
4374 src = EnforceType(B, src, IdTy);
4375 llvm::Value *dstVal = EnforceType(B, dst.
emitRawPointer(CGF), PtrToIdTy);
4377 assert(!threadlocal &&
"EmitObjCGlobalAssign - Threal Local API NYI");
4378 B.CreateCall(GlobalAssignFn, {src, dstVal});
4381void CGObjCGNU::EmitObjCIvarAssign(CodeGenFunction &CGF,
4382 llvm::Value *src, Address dst,
4383 llvm::Value *ivarOffset) {
4385 src = EnforceType(B, src, IdTy);
4386 llvm::Value *dstVal = EnforceType(B, dst.
emitRawPointer(CGF), IdTy);
4387 B.CreateCall(IvarAssignFn, {src, dstVal, ivarOffset});
4390void CGObjCGNU::EmitObjCStrongCastAssign(CodeGenFunction &CGF,
4391 llvm::Value *src, Address dst) {
4393 src = EnforceType(B, src, IdTy);
4394 llvm::Value *dstVal = EnforceType(B, dst.
emitRawPointer(CGF), PtrToIdTy);
4395 B.CreateCall(StrongCastAssignFn, {src, dstVal});
4398void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF,
4401 llvm::Value *Size) {
4403 llvm::Value *DestPtrVal = EnforceType(B, DestPtr.
emitRawPointer(CGF), PtrTy);
4404 llvm::Value *SrcPtrVal = EnforceType(B, SrcPtr.
emitRawPointer(CGF), PtrTy);
4406 B.CreateCall(MemMoveFn, {DestPtrVal, SrcPtrVal,
Size});
4409llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable(
4410 const ObjCInterfaceDecl *ID,
4411 const ObjCIvarDecl *Ivar) {
4412 const std::string Name = GetIVarOffsetVariableName(ID, Ivar);
4416 llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
4417 if (!IvarOffsetPointer)
4418 IvarOffsetPointer =
new llvm::GlobalVariable(
4419 TheModule, llvm::PointerType::getUnqual(VMContext),
false,
4420 llvm::GlobalValue::ExternalLinkage,
nullptr, Name);
4421 return IvarOffsetPointer;
4424LValue CGObjCGNU::EmitObjCValueForIvar(CodeGenFunction &CGF,
4426 llvm::Value *BaseValue,
4427 const ObjCIvarDecl *Ivar,
4428 unsigned CVRQualifiers) {
4429 const ObjCInterfaceDecl *
ID =
4430 ObjectTy->
castAs<ObjCObjectType>()->getInterface();
4431 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4432 EmitIvarOffset(CGF, ID, Ivar));
4451llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF,
4453 const ObjCIvarDecl *Ivar) {
4460 if (RuntimeVersion < 10 ||
4462 return CGF.
Builder.CreateZExtOrBitCast(
4466 llvm::PointerType::getUnqual(VMContext),
4467 ObjCIvarOffsetVariable(
Interface, Ivar),
4471 std::string
name =
"__objc_ivar_offset_value_" +
4474 llvm::Value *Offset = TheModule.getGlobalVariable(name);
4476 auto GV =
new llvm::GlobalVariable(TheModule, IntTy,
4477 false, llvm::GlobalValue::LinkOnceAnyLinkage,
4478 llvm::Constant::getNullValue(IntTy), name);
4483 if (Offset->getType() != PtrDiffTy)
4484 Offset = CGF.
Builder.CreateZExtOrBitCast(Offset, PtrDiffTy);
4488 return llvm::ConstantInt::get(PtrDiffTy, Offset,
true);
4494 switch (Runtime.getKind()) {
4496 if (Runtime.getVersion() >= VersionTuple(2, 0))
4497 return new CGObjCGNUstep2(CGM);
4498 return new CGObjCGNUstep(CGM);
4501 return new CGObjCGCC(CGM);
4504 return new CGObjCObjFW(CGM);
4510 llvm_unreachable(
"these runtimes are not GNU runtimes");
4512 llvm_unreachable(
"bad runtime");
Defines the clang::ASTContext interface.
static const ObjCInterfaceDecl * FindIvarInterface(ASTContext &Context, const ObjCInterfaceDecl *OID, const ObjCIvarDecl *OIVD)
static bool isNamed(const NamedDecl *ND, const char(&Str)[Len])
Result
Implement __builtin_bit_cast and related operations.
static StringRef getTriple(const Command &Job)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Defines the SourceManager interface.
Defines the Objective-C statement AST node classes.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
void getObjCEncodingForType(QualType T, std::string &S, const FieldDecl *Field=nullptr, QualType *NotEncodedT=nullptr) const
Emit the Objective-CC type encoding for the given type T into S.
std::string getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, bool Extended=false) const
Emit the encoded type for the method declaration Decl into S.
std::string getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, const Decl *Container) const
getObjCEncodingForPropertyDecl - Return the encoded type for this method declaration.
const ASTRecordLayout & getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const
Get or compute information about the layout of the specified Objective-C interface.
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
ObjCPropertyImplDecl * getObjCPropertyImplDeclForPropertyDecl(const ObjCPropertyDecl *PD, const Decl *Container) const
QualType getObjCSelType() const
Retrieve the type that corresponds to the predefined Objective-C 'SEL' type.
QualType getObjCIdType() const
Represents the Objective-CC id type.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
void getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT, QualType T, std::string &S, bool Extended) const
getObjCEncodingForMethodParameter - Return the encoded type for a single method parameter or return t...
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
uint64_t getCharWidth() const
Return the size of the character type, in bits.
CharUnits getSize() const
getSize - Get the record size in characters.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::LoadInst * CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, CharUnits Align, const llvm::Twine &Name="")
virtual llvm::Constant * getAddrOfRTTIDescriptor(QualType Ty)=0
virtual CatchTypeInfo getCatchAllTypeInfo()
Implements runtime-specific code generation functions.
void add(RValue rvalue, QualType type)
void addFrom(const CallArgList &other)
Add all the arguments from another CallArgList to this one.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
llvm::CallBase * EmitRuntimeCallOrInvoke(llvm::FunctionCallee callee, ArrayRef< llvm::Value * > args, const Twine &name="")
Emits a call or invoke instruction to the given runtime function.
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
llvm::Value * EmitObjCThrowOperand(const Expr *expr)
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
JumpDest ReturnBlock
ReturnBlock - Unified return block.
llvm::AllocaInst * CreateTempAlloca(llvm::Type *Ty, const Twine &Name="tmp", llvm::Value *ArraySize=nullptr)
CreateTempAlloca - This creates an alloca and inserts it into the entry block if ArraySize is nullptr...
RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **CallOrInvoke, bool IsMustTail, SourceLocation Loc, bool IsVirtualFunctionPointerThunk=false)
EmitCall - Generate a call of the given function, expecting the given result type,...
llvm::Value * LoadObjCSelf()
LoadObjCSelf - Load the value of self.
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
SmallVector< llvm::Value *, 8 > ObjCEHValueStack
ObjCEHValueStack - Stack of Objective-C exception values, used for rethrows.
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
static bool hasAggregateEvaluationKind(QualType T)
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
llvm::LLVMContext & getLLVMContext()
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
This class organizes the cross-function state that is used while generating LLVM code.
void setGVProperties(llvm::GlobalValue *GV, GlobalDecl GD) const
Set visibility, dllimport/dllexport and dso_local.
llvm::Module & getModule() const
llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)
Create or return a runtime function declaration with the specified type and name.
void addCompilerUsedGlobal(llvm::GlobalValue *GV)
Add a global to a list to be added to the llvm.compiler.used metadata.
bool ReturnTypeUsesFPRet(QualType ResultType)
Return true iff the given type uses 'fpret' when used as a return type.
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const TargetInfo & getTarget() const
void addUsedGlobal(llvm::GlobalValue *GV)
Add a global to a list to be added to the llvm.used metadata.
const llvm::DataLayout & getDataLayout() const
CGCXXABI & getCXXABI() const
const llvm::Triple & getTriple() const
bool ReturnTypeHasInReg(const CGFunctionInfo &FI)
Return true iff the given type has inreg set.
ASTContext & getContext() const
bool ReturnTypeUsesSRet(const CGFunctionInfo &FI)
Return true iff the given type uses 'sret' when used as a return type.
const CodeGenOptions & getCodeGenOpts() const
llvm::LLVMContext & getLLVMContext()
llvm::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
ConstantAddress GetAddrOfConstantCString(const std::string &Str, StringRef GlobalName=".str")
Returns a pointer to a character array containing the literal and a terminating '\0' character.
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
const CGFunctionInfo & arrangeObjCMethodDeclaration(const ObjCMethodDecl *MD)
Objective-C methods are C functions with some implicit parameters.
bool isZeroInitializable(QualType T)
IsZeroInitializable - Return whether a type can be zero-initialized (in the C++ sense) with an LLVM z...
llvm::Constant * getPointer() const
void add(llvm::Constant *value)
Add a new value to this initializer.
void addInt(llvm::IntegerType *intTy, uint64_t value, bool isSigned=false)
Add an integer value of a specific type.
void addNullPointer(llvm::PointerType *ptrTy)
Add a null pointer of a specific type.
ArrayBuilder beginArray(llvm::Type *eltTy=nullptr)
llvm::GlobalVariable * finishAndCreateGlobal(As &&...args)
Given that this builder was created by beginning an array or struct directly on a ConstantInitBuilder...
StructBuilder beginStruct(llvm::StructType *ty=nullptr)
void finishAndAddTo(AggregateBuilderBase &parent)
Given that this builder was created by beginning an array or struct component on the given parent bui...
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
Address getAggregateAddress() const
getAggregateAddr() - Return the Value* of the address of the aggregate.
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
llvm::Value * getPointer() const
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
bool isWeakImported() const
Determine whether this is a weak-imported symbol.
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
StringRef getName() const
The name of this FileEntry.
DirectoryEntryRef getDir() const
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
clang::ObjCRuntime ObjCRuntime
std::string ObjCConstantStringClass
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Visibility getVisibility() const
Determines the visibility of this entity.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
const Expr * getThrowExpr() const
const ObjCProtocolList & getReferencedProtocols() const
ObjCCategoryDecl * getCategoryDecl() const
const ObjCInterfaceDecl * getClassInterface() const
classmeth_iterator classmeth_end() const
classmeth_iterator classmeth_begin() const
instmeth_range instance_methods() const
instmeth_iterator instmeth_end() const
instmeth_iterator instmeth_begin() const
prop_range properties() const
classmeth_range class_methods() const
propimpl_range property_impls() const
const ObjCInterfaceDecl * getClassInterface() const
Represents an ObjC class declaration.
all_protocol_iterator all_referenced_protocol_end() const
all_protocol_range all_referenced_protocols() const
ObjCIvarDecl * all_declared_ivar_begin()
all_declared_ivar_begin - return first ivar declared in this class, its extensions and its implementa...
protocol_range protocols() const
all_protocol_iterator all_referenced_protocol_begin() const
ObjCInterfaceDecl * getSuperClass() const
ObjCInterfaceDecl * getDefinition()
Retrieve the definition of this class, or NULL if this class has been forward-declared (with @class) ...
known_extensions_range known_extensions() const
ObjCInterfaceDecl * getDecl() const
Get the declaration of this interface.
ObjCIvarDecl - Represents an ObjC instance variable.
AccessControl getAccessControl() const
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
ObjCIvarDecl * getNextIvar()
ImplicitParamDecl * getSelfDecl() const
Stmt * getBody() const override
Retrieve the body of this method, if it has one.
ObjCMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
bool isDirectMethod() const
True if the method is tagged as objc_direct.
Selector getSelector() const
ImplicitParamDecl * getCmdDecl() const
QualType getReturnType() const
bool isClassMethod() const
const ObjCObjectType * getObjectType() const
Gets the type pointed to by this ObjC pointer.
const ObjCInterfaceType * getInterfaceType() const
If this pointer points to an Objective C @interface type, gets the type for that interface.
ObjCMethodDecl * getGetterMethodDecl() const
ObjCMethodDecl * getSetterMethodDecl() const
ObjCProtocolDecl * getDefinition()
Retrieve the definition of this protocol, if any.
bool isNonRuntimeProtocol() const
This is true iff the protocol is tagged with the objc_non_runtime_protocol attribute.
protocol_iterator protocol_begin() const
protocol_range protocols() const
protocol_iterator protocol_end() const
const VersionTuple & getVersion() const
bool isNonFragile() const
Does this runtime follow the set of implied behaviors for a "non-fragile" ABI?
Kind
The basic Objective-C runtimes that we know about.
@ MacOSX
'macosx' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the non-fragile AB...
@ FragileMacOSX
'macosx-fragile' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the fragil...
@ GNUstep
'gnustep' is the modern non-fragile GNUstep runtime.
@ ObjFW
'objfw' is the Objective-C runtime included in ObjFW
@ iOS
'ios' is the Apple-provided NeXT-derived runtime on iOS or the iOS simulator; it is always non-fragil...
@ GCC
'gcc' is the Objective-C runtime shipped with GCC, implementing a fragile Objective-C ABI
@ WatchOS
'watchos' is a variant of iOS for Apple's watchOS.
A (possibly-)qualified type.
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
@ OCL_None
There is no lifetime qualification on this type.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
std::string getAsString() const
Derive the full selector name (e.g.
OptionalFileEntryRef getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
FileID getMainFileID() const
Returns the FileID of the main source file.
bool containsNonAscii() const
unsigned getLength() const
uint32_t getCodeUnit(size_t i) const
StringRef getString() const
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
static DeclContext * castToDeclContext(const TranslationUnitDecl *D)
const T * castAs() const
Member-template castAs<specific type>.
bool isObjCQualifiedIdType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isObjCIdType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool hasPointerRepresentation() const
Whether this type is represented natively as a pointer.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
CGObjCRuntime * CreateGNUObjCRuntime(CodeGenModule &CGM)
Creates an instance of an Objective-C runtime class.
StringRef getName(const HeaderType T)
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
@ Address
A pointer to a ValueDecl.
Top level wrappers for InstallAPI frontend operations.
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.
int const char * function
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 int32_t
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
CharUnits getIntAlign() const
llvm::IntegerType * Int16Ty
llvm::PointerType * Int8PtrTy
CharUnits getPointerAlign() const