diff options
Diffstat (limited to 'lib/CodeGen/CGObjCGNU.cpp')
-rw-r--r-- | lib/CodeGen/CGObjCGNU.cpp | 296 |
1 files changed, 203 insertions, 93 deletions
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 688e9924be50..db0bd951c1e8 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -18,7 +18,6 @@ #include "CodeGenModule.h" #include "CodeGenFunction.h" #include "CGCleanup.h" - #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" @@ -104,8 +103,6 @@ class LazyRuntimeFunction { /// GNUstep). class CGObjCGNU : public CGObjCRuntime { protected: - /// The module that is using this class - CodeGenModule &CGM; /// The LLVM module into which output is inserted llvm::Module &TheModule; /// strut objc_super. Used for sending messages to super. This structure @@ -187,7 +184,7 @@ protected: std::string name = prefix + Str; llvm::Constant *ConstStr = TheModule.getGlobalVariable(name); if (!ConstStr) { - llvm::Constant *value = llvm::ConstantArray::get(VMContext, Str, true); + llvm::Constant *value = llvm::ConstantDataArray::getString(VMContext,Str); ConstStr = new llvm::GlobalVariable(TheModule, value->getType(), true, llvm::GlobalValue::LinkOnceODRLinkage, value, prefix + Str); } @@ -288,6 +285,10 @@ private: LazyRuntimeFunction IvarAssignFn, StrongCastAssignFn, MemMoveFn, WeakReadFn, WeakAssignFn, GlobalAssignFn; + typedef std::pair<std::string, std::string> ClassAliasPair; + /// All classes that have aliases set for them. + std::vector<ClassAliasPair> ClassAliases; + protected: /// Function used for throwing Objective-C exceptions. LazyRuntimeFunction ExceptionThrowFn; @@ -336,10 +337,9 @@ private: /// containing a size and an array of structures containing instance variable /// metadata. This is used purely for introspection in the fragile ABI. In /// the non-fragile ABI, it's used for instance variable fixup. - llvm::Constant *GenerateIvarList( - const SmallVectorImpl<llvm::Constant *> &IvarNames, - const SmallVectorImpl<llvm::Constant *> &IvarTypes, - const SmallVectorImpl<llvm::Constant *> &IvarOffsets); + llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames, + ArrayRef<llvm::Constant *> IvarTypes, + ArrayRef<llvm::Constant *> IvarOffsets); /// Generates a method list structure. This is a structure containing a size /// and an array of structures containing method metadata. /// @@ -347,8 +347,8 @@ private: /// pointer allowing them to be chained together in a linked list. llvm::Constant *GenerateMethodList(const StringRef &ClassName, const StringRef &CategoryName, - const SmallVectorImpl<Selector> &MethodSels, - const SmallVectorImpl<llvm::Constant *> &MethodTypes, + ArrayRef<Selector> MethodSels, + ArrayRef<llvm::Constant *> MethodTypes, bool isClassMethodList); /// Emits an empty protocol. This is used for @protocol() where no protocol /// is found. The runtime will (hopefully) fix up the pointer to refer to the @@ -361,8 +361,7 @@ private: SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes); /// Generates a list of referenced protocols. Classes, categories, and /// protocols all use this structure. - llvm::Constant *GenerateProtocolList( - const SmallVectorImpl<std::string> &Protocols); + llvm::Constant *GenerateProtocolList(ArrayRef<std::string> Protocols); /// To ensure that all protocols are seen by the runtime, we add a category on /// a class defined in the runtime, declaring no methods, but adopting the /// protocols. This is a horribly ugly hack, but it allows us to collect all @@ -387,8 +386,8 @@ private: /// Generates a method list. This is used by protocols to define the required /// and optional methods. llvm::Constant *GenerateProtocolMethodList( - const SmallVectorImpl<llvm::Constant *> &MethodNames, - const SmallVectorImpl<llvm::Constant *> &MethodTypes); + ArrayRef<llvm::Constant *> MethodNames, + ArrayRef<llvm::Constant *> MethodTypes); /// Returns a selector with the specified type encoding. An empty string is /// used to return an untyped selector (with the types field set to NULL). llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel, @@ -427,7 +426,7 @@ protected: /// significant bit being assumed to come first in the bitfield. Therefore, /// a bitfield with the 64th bit set will be (int64_t)&{ 2, [0, 1<<31] }, /// while a bitfield / with the 63rd bit set will be 1<<64. - llvm::Constant *MakeBitField(llvm::SmallVectorImpl<bool> &bits); + llvm::Constant *MakeBitField(ArrayRef<bool> bits); public: CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion, unsigned protocolClassVersion); @@ -466,13 +465,17 @@ public: const ObjCContainerDecl *CD); virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); + virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD); virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder, const ObjCProtocolDecl *PD); virtual void GenerateProtocol(const ObjCProtocolDecl *PD); virtual llvm::Function *ModuleInitFunction(); virtual llvm::Constant *GetPropertyGetFunction(); virtual llvm::Constant *GetPropertySetFunction(); + virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic, + bool copy); virtual llvm::Constant *GetSetStructFunction(); + virtual llvm::Constant *GetCppAtomicObjectFunction(); virtual llvm::Constant *GetGetStructFunction(); virtual llvm::Constant *EnumerationMutationFunction(); @@ -539,8 +542,8 @@ protected: llvm::MDNode *node) { CGBuilderTy &Builder = CGF.Builder; llvm::Value *args[] = { - EnforceType(Builder, Receiver, IdTy), - EnforceType(Builder, cmd, SelectorTy) }; + EnforceType(Builder, Receiver, IdTy), + EnforceType(Builder, cmd, SelectorTy) }; llvm::CallSite imp = CGF.EmitCallOrInvoke(MsgLookupFn, args); imp->setMetadata(msgSendMDKind, node); return imp.getInstruction(); @@ -599,9 +602,9 @@ class CGObjCGNUstep : public CGObjCGNU { LookupFn->setDoesNotCapture(1); llvm::Value *args[] = { - EnforceType(Builder, ReceiverPtr, PtrToIdTy), - EnforceType(Builder, cmd, SelectorTy), - EnforceType(Builder, self, IdTy) }; + EnforceType(Builder, ReceiverPtr, PtrToIdTy), + EnforceType(Builder, cmd, SelectorTy), + EnforceType(Builder, self, IdTy) }; llvm::CallSite slot = CGF.EmitCallOrInvoke(LookupFn, args); slot.setOnlyReadsMemory(); slot->setMetadata(msgSendMDKind, node); @@ -638,7 +641,7 @@ class CGObjCGNUstep : public CGObjCGNU { SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy, PtrToObjCSuperTy, SelectorTy, NULL); // If we're in ObjC++ mode, then we want to make - if (CGM.getLangOptions().CPlusPlus) { + if (CGM.getLangOpts().CPlusPlus) { llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext); // void *__cxa_begin_catch(void *e) EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy, NULL); @@ -683,9 +686,9 @@ static std::string SymbolNameForMethod(const StringRef &ClassName, CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion, unsigned protocolClassVersion) - : CGM(cgm), TheModule(CGM.getModule()), VMContext(cgm.getLLVMContext()), - ClassPtrAlias(0), MetaClassPtrAlias(0), RuntimeVersion(runtimeABIVersion), - ProtocolVersion(protocolClassVersion) { + : CGObjCRuntime(cgm), TheModule(CGM.getModule()), + VMContext(cgm.getLLVMContext()), ClassPtrAlias(0), MetaClassPtrAlias(0), + RuntimeVersion(runtimeABIVersion), ProtocolVersion(protocolClassVersion) { msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend"); @@ -770,7 +773,7 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion, IMPTy = llvm::PointerType::getUnqual(llvm::FunctionType::get(IdTy, IMPArgs, true)); - const LangOptions &Opts = CGM.getLangOptions(); + const LangOptions &Opts = CGM.getLangOpts(); if ((Opts.getGC() != LangOptions::NonGC) || Opts.ObjCAutoRefCount) RuntimeVersion = 10; @@ -879,14 +882,14 @@ llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl } llvm::Constant *CGObjCGNU::GetEHType(QualType T) { - if (!CGM.getLangOptions().CPlusPlus) { + if (!CGM.getLangOpts().CPlusPlus) { if (T->isObjCIdType() || T->isObjCQualifiedIdType()) { // With the old ABI, there was only one kind of catchall, which broke // foreign exceptions. With the new ABI, we use __objc_id_typeinfo as // a pointer indicating object catchalls, and NULL to indicate real // catchalls - if (CGM.getLangOptions().ObjCNonFragileABI) { + if (CGM.getLangOpts().ObjCNonFragileABI) { return MakeConstantString("@id"); } else { return 0; @@ -930,7 +933,8 @@ llvm::Constant *CGObjCGNU::GetEHType(QualType T) { // Return the existing typeinfo if it exists llvm::Constant *typeinfo = TheModule.getGlobalVariable(typeinfoName); - if (typeinfo) return typeinfo; + if (typeinfo) + return llvm::ConstantExpr::getBitCast(typeinfo, PtrToInt8Ty); // Otherwise create it. @@ -970,12 +974,27 @@ llvm::Constant *CGObjCGNU::GenerateConstantString(const StringLiteral *SL) { if (old != ObjCStrings.end()) return old->getValue(); + StringRef StringClass = CGM.getLangOpts().ObjCConstantStringClass; + + if (StringClass.empty()) StringClass = "NXConstantString"; + + std::string Sym = "_OBJC_CLASS_"; + Sym += StringClass; + + llvm::Constant *isa = TheModule.getNamedGlobal(Sym); + + if (!isa) + isa = new llvm::GlobalVariable(TheModule, IdTy, /* isConstant */false, + llvm::GlobalValue::ExternalWeakLinkage, 0, Sym); + else if (isa->getType() != PtrToIdTy) + isa = llvm::ConstantExpr::getBitCast(isa, PtrToIdTy); + std::vector<llvm::Constant*> Ivars; - Ivars.push_back(NULLPtr); + Ivars.push_back(isa); Ivars.push_back(MakeConstantString(Str)); Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size())); llvm::Constant *ObjCStr = MakeGlobal( - llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL), + llvm::StructType::get(PtrToIdTy, PtrToInt8Ty, IntTy, NULL), Ivars, ".objc_str"); ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty); ObjCStrings[Str] = ObjCStr; @@ -998,7 +1017,7 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF, const CallArgList &CallArgs, const ObjCMethodDecl *Method) { CGBuilderTy &Builder = CGF.Builder; - if (CGM.getLangOptions().getGC() == LangOptions::GCOnly) { + if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) { if (Sel == RetainSel || Sel == AutoreleaseSel) { return RValue::get(EnforceType(Builder, Receiver, CGM.getTypes().ConvertType(ResultType))); @@ -1017,9 +1036,7 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF, ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType()); ActualArgs.addFrom(CallArgs); - CodeGenTypes &Types = CGM.getTypes(); - const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs, - FunctionType::ExtInfo()); + MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs); llvm::Value *ReceiverClass = 0; if (isCategoryImpl) { @@ -1072,12 +1089,10 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF, Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1)); ObjCSuper = EnforceType(Builder, ObjCSuper, PtrToObjCSuperTy); - llvm::FunctionType *impType = - Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false); // Get the IMP llvm::Value *imp = LookupIMPSuper(CGF, ObjCSuper, cmd); - imp = EnforceType(Builder, imp, llvm::PointerType::getUnqual(impType)); + imp = EnforceType(Builder, imp, MSI.MessengerType); llvm::Value *impMD[] = { llvm::MDString::get(VMContext, Sel.getAsString()), @@ -1087,8 +1102,7 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF, llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD); llvm::Instruction *call; - RValue msgRet = CGF.EmitCall(FnInfo, imp, Return, ActualArgs, - 0, &call); + RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs, 0, &call); call->setMetadata(msgSendMDKind, node); return msgRet; } @@ -1106,7 +1120,7 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, CGBuilderTy &Builder = CGF.Builder; // Strip out message sends to retain / release in GC mode - if (CGM.getLangOptions().getGC() == LangOptions::GCOnly) { + if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) { if (Sel == RetainSel || Sel == AutoreleaseSel) { return RValue::get(EnforceType(Builder, Receiver, CGM.getTypes().ConvertType(ResultType))); @@ -1161,27 +1175,46 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, }; llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD); - // Get the IMP to call - llvm::Value *imp = LookupIMP(CGF, Receiver, cmd, node); - CallArgList ActualArgs; ActualArgs.add(RValue::get(Receiver), ASTIdTy); ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType()); ActualArgs.addFrom(CallArgs); - CodeGenTypes &Types = CGM.getTypes(); - const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs, - FunctionType::ExtInfo()); - llvm::FunctionType *impType = - Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false); - imp = EnforceType(Builder, imp, llvm::PointerType::getUnqual(impType)); + MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs); + + // Get the IMP to call + llvm::Value *imp; + + // If we have non-legacy dispatch specified, we try using the objc_msgSend() + // functions. These are not supported on all platforms (or all runtimes on a + // given platform), so we + switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) { + case CodeGenOptions::Legacy: + imp = LookupIMP(CGF, Receiver, cmd, node); + break; + case CodeGenOptions::Mixed: + case CodeGenOptions::NonLegacy: + if (CGM.ReturnTypeUsesFPRet(ResultType)) { + imp = CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true), + "objc_msgSend_fpret"); + } else if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) { + // The actual types here don't matter - we're going to bitcast the + // function anyway + imp = CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true), + "objc_msgSend_stret"); + } else { + imp = CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true), + "objc_msgSend"); + } + } + + // Reset the receiver in case the lookup modified it + ActualArgs[0] = CallArg(RValue::get(Receiver), ASTIdTy, false); + imp = EnforceType(Builder, imp, MSI.MessengerType); - // For sender-aware dispatch, we pass the sender as the third argument to a - // lookup function. When sending messages from C code, the sender is nil. - // objc_msg_lookup_sender(id *receiver, SEL selector, id sender); llvm::Instruction *call; - RValue msgRet = CGF.EmitCall(FnInfo, imp, Return, ActualArgs, + RValue msgRet = CGF.EmitCall(MSI.CallInfo, imp, Return, ActualArgs, 0, &call); call->setMetadata(msgSendMDKind, node); @@ -1225,11 +1258,12 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF, /// Generates a MethodList. Used in construction of a objc_class and /// objc_category structures. -llvm::Constant *CGObjCGNU::GenerateMethodList(const StringRef &ClassName, - const StringRef &CategoryName, - const SmallVectorImpl<Selector> &MethodSels, - const SmallVectorImpl<llvm::Constant *> &MethodTypes, - bool isClassMethodList) { +llvm::Constant *CGObjCGNU:: +GenerateMethodList(const StringRef &ClassName, + const StringRef &CategoryName, + ArrayRef<Selector> MethodSels, + ArrayRef<llvm::Constant *> MethodTypes, + bool isClassMethodList) { if (MethodSels.empty()) return NULLPtr; // Get the method structure type. @@ -1282,10 +1316,10 @@ llvm::Constant *CGObjCGNU::GenerateMethodList(const StringRef &ClassName, } /// Generates an IvarList. Used in construction of a objc_class. -llvm::Constant *CGObjCGNU::GenerateIvarList( - const SmallVectorImpl<llvm::Constant *> &IvarNames, - const SmallVectorImpl<llvm::Constant *> &IvarTypes, - const SmallVectorImpl<llvm::Constant *> &IvarOffsets) { +llvm::Constant *CGObjCGNU:: +GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames, + ArrayRef<llvm::Constant *> IvarTypes, + ArrayRef<llvm::Constant *> IvarOffsets) { if (IvarNames.size() == 0) return NULLPtr; // Get the method structure type. @@ -1345,7 +1379,7 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure( // anyway; the classes will still work with the GNU runtime, they will just // be ignored. llvm::StructType *ClassTy = llvm::StructType::get( - PtrToInt8Ty, // class_pointer + PtrToInt8Ty, // isa PtrToInt8Ty, // super_class PtrToInt8Ty, // name LongTy, // version @@ -1396,14 +1430,25 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure( Elements.push_back(WeakIvarBitmap); // Create an instance of the structure // This is now an externally visible symbol, so that we can speed up class - // messages in the next ABI. - return MakeGlobal(ClassTy, Elements, (isMeta ? "_OBJC_METACLASS_": - "_OBJC_CLASS_") + std::string(Name), llvm::GlobalValue::ExternalLinkage); + // messages in the next ABI. We may already have some weak references to + // this, so check and fix them properly. + std::string ClassSym((isMeta ? "_OBJC_METACLASS_": "_OBJC_CLASS_") + + std::string(Name)); + llvm::GlobalVariable *ClassRef = TheModule.getNamedGlobal(ClassSym); + llvm::Constant *Class = MakeGlobal(ClassTy, Elements, ClassSym, + llvm::GlobalValue::ExternalLinkage); + if (ClassRef) { + ClassRef->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(Class, + ClassRef->getType())); + ClassRef->removeFromParent(); + Class->setName(ClassSym); + } + return Class; } -llvm::Constant *CGObjCGNU::GenerateProtocolMethodList( - const SmallVectorImpl<llvm::Constant *> &MethodNames, - const SmallVectorImpl<llvm::Constant *> &MethodTypes) { +llvm::Constant *CGObjCGNU:: +GenerateProtocolMethodList(ArrayRef<llvm::Constant *> MethodNames, + ArrayRef<llvm::Constant *> MethodTypes) { // Get the method structure type. llvm::StructType *ObjCMethodDescTy = llvm::StructType::get( PtrToInt8Ty, // Really a selector, but the runtime does the casting for us. @@ -1430,8 +1475,7 @@ llvm::Constant *CGObjCGNU::GenerateProtocolMethodList( } // Create the protocol list structure used in classes, categories and so on -llvm::Constant *CGObjCGNU::GenerateProtocolList( - const SmallVectorImpl<std::string> &Protocols) { +llvm::Constant *CGObjCGNU::GenerateProtocolList(ArrayRef<std::string>Protocols){ llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrToInt8Ty, Protocols.size()); llvm::StructType *ProtocolListTy = llvm::StructType::get( @@ -1506,6 +1550,11 @@ llvm::Constant *CGObjCGNU::GenerateEmptyProtocol( void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { ASTContext &Context = CGM.getContext(); std::string ProtocolName = PD->getNameAsString(); + + // Use the protocol definition, if there is one. + if (const ObjCProtocolDecl *Def = PD->getDefinition()) + PD = Def; + SmallVector<std::string, 16> Protocols; for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(), E = PD->protocol_end(); PI != E; ++PI) @@ -1723,7 +1772,7 @@ void CGObjCGNU::GenerateProtocolHolderCategory(void) { /// significant bit being assumed to come first in the bitfield. Therefore, a /// bitfield with the 64th bit set will be (int64_t)&{ 2, [0, 1<<31] }, while a /// bitfield / with the 63rd bit set will be 1<<64. -llvm::Constant *CGObjCGNU::MakeBitField(llvm::SmallVectorImpl<bool> &bits) { +llvm::Constant *CGObjCGNU::MakeBitField(ArrayRef<bool> bits) { int bitCount = bits.size(); int ptrBits = (TheModule.getPointerSize() == llvm::Module::Pointer32) ? 32 : 64; @@ -1881,6 +1930,15 @@ llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OI ".objc_property_list"); } +void CGObjCGNU::RegisterAlias(const ObjCCompatibleAliasDecl *OAD) { + // Get the class declaration for which the alias is specified. + ObjCInterfaceDecl *ClassDecl = + const_cast<ObjCInterfaceDecl *>(OAD->getClassInterface()); + std::string ClassName = ClassDecl->getNameAsString(); + std::string AliasName = OAD->getNameAsString(); + ClassAliases.push_back(ClassAliasPair(ClassName,AliasName)); +} + void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { ASTContext &Context = CGM.getContext(); @@ -1926,7 +1984,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize().getQuantity(); // For non-fragile ivars, set the instance size to 0 - {the size of just this // class}. The runtime will then set this to the correct value on load. - if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { + if (CGM.getContext().getLangOpts().ObjCNonFragileABI) { instanceSize = 0 - (instanceSize - superInstanceSize); } @@ -1941,7 +1999,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { // Get the offset uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD); uint64_t Offset = BaseOffset; - if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { + if (CGM.getContext().getLangOpts().ObjCNonFragileABI) { Offset = BaseOffset - superInstanceSize; } llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset); @@ -2013,9 +2071,9 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { } // Collect the names of referenced protocols SmallVector<std::string, 16> Protocols; - const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols(); - for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(), - E = Protos.end(); I != E; ++I) + for (ObjCInterfaceDecl::protocol_iterator + I = ClassDecl->protocol_begin(), + E = ClassDecl->protocol_end(); I != E; ++I) Protocols.push_back((*I)->getNameAsString()); @@ -2063,15 +2121,16 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { // Get the existing variable, if one exists. llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name); if (offset) { - offset->setInitializer(offsetValue); - // If this is the real definition, change its linkage type so that - // different modules will use this one, rather than their private - // copy. - offset->setLinkage(llvm::GlobalValue::ExternalLinkage); + offset->setInitializer(offsetValue); + // If this is the real definition, change its linkage type so that + // different modules will use this one, rather than their private + // copy. + offset->setLinkage(llvm::GlobalValue::ExternalLinkage); } else { - // Add a new alias if there isn't one already. - offset = new llvm::GlobalVariable(TheModule, offsetValue->getType(), - false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name); + // Add a new alias if there isn't one already. + offset = new llvm::GlobalVariable(TheModule, offsetValue->getType(), + false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name); + (void) offset; // Silence dead store warning. } ++ivarIndex; } @@ -2135,7 +2194,7 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { ConstantStrings.size() + 1); ConstantStrings.push_back(NULLPtr); - StringRef StringClass = CGM.getLangOptions().ObjCConstantStringClass; + StringRef StringClass = CGM.getLangOpts().ObjCConstantStringClass; if (StringClass.empty()) StringClass = "NXConstantString"; @@ -2263,12 +2322,12 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { Elements.push_back(SymTab); if (RuntimeVersion >= 10) - switch (CGM.getLangOptions().getGC()) { + switch (CGM.getLangOpts().getGC()) { case LangOptions::GCOnly: Elements.push_back(llvm::ConstantInt::get(IntTy, 2)); break; case LangOptions::NonGC: - if (CGM.getLangOptions().ObjCAutoRefCount) + if (CGM.getLangOpts().ObjCAutoRefCount) Elements.push_back(llvm::ConstantInt::get(IntTy, 1)); else Elements.push_back(llvm::ConstantInt::get(IntTy, 0)); @@ -2296,6 +2355,46 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { llvm::PointerType::getUnqual(ModuleTy), true); llvm::Value *Register = CGM.CreateRuntimeFunction(FT, "__objc_exec_class"); Builder.CreateCall(Register, Module); + + if (!ClassAliases.empty()) { + llvm::Type *ArgTypes[2] = {PtrTy, PtrToInt8Ty}; + llvm::FunctionType *RegisterAliasTy = + llvm::FunctionType::get(Builder.getVoidTy(), + ArgTypes, false); + llvm::Function *RegisterAlias = llvm::Function::Create( + RegisterAliasTy, + llvm::GlobalValue::ExternalWeakLinkage, "class_registerAlias_np", + &TheModule); + llvm::BasicBlock *AliasBB = + llvm::BasicBlock::Create(VMContext, "alias", LoadFunction); + llvm::BasicBlock *NoAliasBB = + llvm::BasicBlock::Create(VMContext, "no_alias", LoadFunction); + + // Branch based on whether the runtime provided class_registerAlias_np() + llvm::Value *HasRegisterAlias = Builder.CreateICmpNE(RegisterAlias, + llvm::Constant::getNullValue(RegisterAlias->getType())); + Builder.CreateCondBr(HasRegisterAlias, AliasBB, NoAliasBB); + + // The true branch (has alias registration fucntion): + Builder.SetInsertPoint(AliasBB); + // Emit alias registration calls: + for (std::vector<ClassAliasPair>::iterator iter = ClassAliases.begin(); + iter != ClassAliases.end(); ++iter) { + llvm::Constant *TheClass = + TheModule.getGlobalVariable(("_OBJC_CLASS_" + iter->first).c_str(), + true); + if (0 != TheClass) { + TheClass = llvm::ConstantExpr::getBitCast(TheClass, PtrTy); + Builder.CreateCall2(RegisterAlias, TheClass, + MakeConstantString(iter->second)); + } + } + // Jump to end: + Builder.CreateBr(NoAliasBB); + + // Missing alias registration function, just return from the function: + Builder.SetInsertPoint(NoAliasBB); + } Builder.CreateRetVoid(); return LoadFunction; @@ -2312,7 +2411,7 @@ llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD, CodeGenTypes &Types = CGM.getTypes(); llvm::FunctionType *MethodTy = - Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic()); + Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD)); std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName, MethodName, isClassMethod); @@ -2332,12 +2431,20 @@ llvm::Constant *CGObjCGNU::GetPropertySetFunction() { return SetPropertyFn; } +llvm::Constant *CGObjCGNU::GetOptimizedPropertySetFunction(bool atomic, + bool copy) { + return 0; +} + llvm::Constant *CGObjCGNU::GetGetStructFunction() { return GetStructPropertyFn; } llvm::Constant *CGObjCGNU::GetSetStructFunction() { return SetStructPropertyFn; } +llvm::Constant *CGObjCGNU::GetCppAtomicObjectFunction() { + return 0; +} llvm::Constant *CGObjCGNU::EnumerationMutationFunction() { return EnumerationMutationFn; @@ -2487,7 +2594,7 @@ llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable( // to replace it with the real version for a library. In non-PIC code you // must compile with the fragile ABI if you want to use ivars from a // GCC-compiled class. - if (CGM.getLangOptions().PICLevel) { + if (CGM.getLangOpts().PICLevel || CGM.getLangOpts().PIELevel) { llvm::GlobalVariable *IvarOffsetGV = new llvm::GlobalVariable(TheModule, Int32Ty, false, llvm::GlobalValue::PrivateLinkage, OffsetGuess, Name+".guess"); @@ -2533,7 +2640,7 @@ static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context, llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF, const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar) { - if (CGM.getLangOptions().ObjCNonFragileABI) { + if (CGM.getLangOpts().ObjCNonFragileABI) { Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar); if (RuntimeVersion < 10) return CGF.Builder.CreateZExtOrBitCast( @@ -2547,7 +2654,10 @@ llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF, Offset = new llvm::GlobalVariable(TheModule, IntTy, false, llvm::GlobalValue::LinkOnceAnyLinkage, llvm::Constant::getNullValue(IntTy), name); - return CGF.Builder.CreateLoad(Offset); + Offset = CGF.Builder.CreateLoad(Offset); + if (Offset->getType() != PtrDiffTy) + Offset = CGF.Builder.CreateZExtOrBitCast(Offset, PtrDiffTy); + return Offset; } uint64_t Offset = ComputeIvarBaseOffset(CGF.CGM, Interface, Ivar); return llvm::ConstantInt::get(PtrDiffTy, Offset, /*isSigned*/true); @@ -2555,7 +2665,7 @@ llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF, CGObjCRuntime * clang::CodeGen::CreateGNUObjCRuntime(CodeGenModule &CGM) { - if (CGM.getLangOptions().ObjCNonFragileABI) + if (CGM.getLangOpts().ObjCNonFragileABI) return new CGObjCGNUstep(CGM); return new CGObjCGCC(CGM); } |