diff options
Diffstat (limited to 'lib/CodeGen/CGObjCGNU.cpp')
-rw-r--r-- | lib/CodeGen/CGObjCGNU.cpp | 156 |
1 files changed, 110 insertions, 46 deletions
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 6d129d0..68d234d 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -33,7 +33,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/Compiler.h" -#include "llvm/Target/TargetData.h" +#include "llvm/DataLayout.h" #include <cstdarg> @@ -224,6 +224,25 @@ protected: llvm::ArrayType *ArrayTy = llvm::ArrayType::get(Ty, V.size()); return MakeGlobal(ArrayTy, V, Name, linkage); } + /// Returns a property name and encoding string. + llvm::Constant *MakePropertyEncodingString(const ObjCPropertyDecl *PD, + const Decl *Container) { + ObjCRuntime R = CGM.getLangOpts().ObjCRuntime; + if ((R.getKind() == ObjCRuntime::GNUstep) && + (R.getVersion() >= VersionTuple(1, 6))) { + std::string NameAndAttributes; + std::string TypeStr; + CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr); + NameAndAttributes += '\0'; + NameAndAttributes += TypeStr.length() + 3; + NameAndAttributes += TypeStr; + NameAndAttributes += '\0'; + NameAndAttributes += PD->getNameAsString(); + return llvm::ConstantExpr::getGetElementPtr( + CGM.GetAddrOfConstantString(NameAndAttributes), Zeros); + } + return MakeConstantString(PD->getNameAsString()); + } /// Ensures that the value has the required type, by inserting a bitcast if /// required. This function lets us avoid inserting bitcasts that are /// redundant. @@ -514,7 +533,10 @@ public: const CGBlockInfo &blockInfo) { return NULLPtr; } - + virtual llvm::Constant *BuildRCBlockLayout(CodeGenModule &CGM, + const CGBlockInfo &blockInfo) { + return NULLPtr; + } virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name) { return 0; } @@ -578,6 +600,8 @@ class CGObjCGNUstep : public CGObjCGNU { /// Type of an slot structure pointer. This is returned by the various /// lookup functions. llvm::Type *SlotTy; + public: + virtual llvm::Constant *GetEHType(QualType T); protected: virtual llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver, @@ -653,11 +677,40 @@ class CGObjCGNUstep : public CGObjCGNU { } }; -/// The ObjFW runtime, which closely follows the GCC runtime's -/// compiler ABI. Support here is due to Jonathan Schleifer, the -/// ObjFW maintainer. -class CGObjCObjFW : public CGObjCGCC { - /// Emit class references unconditionally as direct symbol references. +/// Support for the ObjFW runtime. Support here is due to +/// Jonathan Schleifer <js@webkeks.org>, the ObjFW maintainer. +class CGObjCObjFW: public CGObjCGNU { +protected: + /// The GCC ABI message lookup function. Returns an IMP pointing to the + /// method implementation for this message. + LazyRuntimeFunction MsgLookupFn; + /// The GCC ABI superclass message lookup function. Takes a pointer to a + /// structure describing the receiver and the class, and a selector as + /// arguments. Returns the IMP for the corresponding method. + LazyRuntimeFunction MsgLookupSuperFn; + + virtual llvm::Value *LookupIMP(CodeGenFunction &CGF, + llvm::Value *&Receiver, + llvm::Value *cmd, + llvm::MDNode *node) { + CGBuilderTy &Builder = CGF.Builder; + llvm::Value *args[] = { + EnforceType(Builder, Receiver, IdTy), + EnforceType(Builder, cmd, SelectorTy) }; + llvm::CallSite imp = CGF.EmitCallOrInvoke(MsgLookupFn, args); + imp->setMetadata(msgSendMDKind, node); + return imp.getInstruction(); + } + + virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, + llvm::Value *ObjCSuper, + llvm::Value *cmd) { + CGBuilderTy &Builder = CGF.Builder; + llvm::Value *lookupArgs[] = {EnforceType(Builder, ObjCSuper, + PtrToObjCSuperTy), cmd}; + return Builder.CreateCall(MsgLookupSuperFn, lookupArgs); + } + virtual llvm::Value *GetClassNamed(CGBuilderTy &Builder, const std::string &Name, bool isWeak) { if (isWeak) @@ -678,7 +731,13 @@ class CGObjCObjFW : public CGObjCGCC { } public: - CGObjCObjFW(CodeGenModule &Mod): CGObjCGCC(Mod) {} + CGObjCObjFW(CodeGenModule &Mod): CGObjCGNU(Mod, 9, 3) { + // IMP objc_msg_lookup(id, SEL); + MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy, NULL); + // IMP objc_msg_lookup_super(struct objc_super*, SEL); + MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy, + PtrToObjCSuperTy, SelectorTy, NULL); + } }; } // end anonymous namespace @@ -909,29 +968,30 @@ llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl } llvm::Constant *CGObjCGNU::GetEHType(QualType T) { - 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.getLangOpts().ObjCRuntime.isNonFragile()) { - return MakeConstantString("@id"); - } else { - return 0; - } - } - - // All other types should be Objective-C interface pointer types. - const ObjCObjectPointerType *OPT = - T->getAs<ObjCObjectPointerType>(); - assert(OPT && "Invalid @catch type."); - const ObjCInterfaceDecl *IDecl = - OPT->getObjectType()->getInterface(); - assert(IDecl && "Invalid @catch type."); - return MakeConstantString(IDecl->getIdentifier()->getName()); + 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.getLangOpts().ObjCRuntime.isNonFragile()) { + return MakeConstantString("@id"); + } else { + return 0; + } } + + // All other types should be Objective-C interface pointer types. + const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>(); + assert(OPT && "Invalid @catch type."); + const ObjCInterfaceDecl *IDecl = OPT->getObjectType()->getInterface(); + assert(IDecl && "Invalid @catch type."); + return MakeConstantString(IDecl->getIdentifier()->getName()); +} + +llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) { + if (!CGM.getLangOpts().CPlusPlus) + return CGObjCGNU::GetEHType(T); + // For Objective-C++, we want to provide the ability to catch both C++ and // Objective-C objects in the same function. @@ -1436,7 +1496,7 @@ llvm::Constant *CGObjCGNU::GenerateClassStructure( Elements.push_back(Zero); Elements.push_back(llvm::ConstantInt::get(LongTy, info)); if (isMeta) { - llvm::TargetData td(&TheModule); + llvm::DataLayout td(&TheModule); Elements.push_back( llvm::ConstantInt::get(LongTy, td.getTypeSizeInBits(ClassTy) / @@ -1595,13 +1655,13 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { std::string TypeStr; Context.getObjCEncodingForMethodDecl(*iter, TypeStr); if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) { - InstanceMethodNames.push_back( - MakeConstantString((*iter)->getSelector().getAsString())); - InstanceMethodTypes.push_back(MakeConstantString(TypeStr)); - } else { OptionalInstanceMethodNames.push_back( MakeConstantString((*iter)->getSelector().getAsString())); OptionalInstanceMethodTypes.push_back(MakeConstantString(TypeStr)); + } else { + InstanceMethodNames.push_back( + MakeConstantString((*iter)->getSelector().getAsString())); + InstanceMethodTypes.push_back(MakeConstantString(TypeStr)); } } // Collect information about class methods: @@ -1615,13 +1675,13 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { std::string TypeStr; Context.getObjCEncodingForMethodDecl((*iter),TypeStr); if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) { - ClassMethodNames.push_back( - MakeConstantString((*iter)->getSelector().getAsString())); - ClassMethodTypes.push_back(MakeConstantString(TypeStr)); - } else { OptionalClassMethodNames.push_back( MakeConstantString((*iter)->getSelector().getAsString())); OptionalClassMethodTypes.push_back(MakeConstantString(TypeStr)); + } else { + ClassMethodNames.push_back( + MakeConstantString((*iter)->getSelector().getAsString())); + ClassMethodTypes.push_back(MakeConstantString(TypeStr)); } } @@ -1656,7 +1716,9 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { std::vector<llvm::Constant*> Fields; ObjCPropertyDecl *property = *iter; - Fields.push_back(MakeConstantString(property->getNameAsString())); + + Fields.push_back(MakePropertyEncodingString(property, PD)); + Fields.push_back(llvm::ConstantInt::get(Int8Ty, property->getPropertyAttributes())); Fields.push_back(llvm::ConstantInt::get(Int8Ty, 0)); @@ -1909,7 +1971,7 @@ llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OI bool isSynthesized = (propertyImpl->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); - Fields.push_back(MakeConstantString(property->getNameAsString())); + Fields.push_back(MakePropertyEncodingString(property, OID)); Fields.push_back(llvm::ConstantInt::get(Int8Ty, property->getPropertyAttributes())); Fields.push_back(llvm::ConstantInt::get(Int8Ty, isSynthesized)); @@ -2011,7 +2073,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().getLangOpts().ObjCRuntime.isNonFragile()) { + if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) { instanceSize = 0 - (instanceSize - superInstanceSize); } @@ -2026,7 +2088,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { // Get the offset uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD); uint64_t Offset = BaseOffset; - if (CGM.getContext().getLangOpts().ObjCRuntime.isNonFragile()) { + if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) { Offset = BaseOffset - superInstanceSize; } llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset); @@ -2334,7 +2396,7 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { // Runtime version, used for ABI compatibility checking. Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion)); // sizeof(ModuleTy) - llvm::TargetData td(&TheModule); + llvm::DataLayout td(&TheModule); Elements.push_back( llvm::ConstantInt::get(LongTy, td.getTypeSizeInBits(ModuleTy) / @@ -2488,7 +2550,7 @@ void CGObjCGNU::EmitTryStmt(CodeGenFunction &CGF, // Unlike the Apple non-fragile runtimes, which also uses // unwind-based zero cost exceptions, the GNU Objective C runtime's // EH support isn't a veneer over C++ EH. Instead, exception - // objects are created by __objc_exception_throw and destroyed by + // objects are created by objc_exception_throw and destroyed by // the personality function; this avoids the need for bracketing // catch handlers with calls to __blah_begin_catch/__blah_end_catch // (or even _Unwind_DeleteException), but probably doesn't @@ -2513,7 +2575,9 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF, ExceptionAsObject = CGF.ObjCEHValueStack.back(); } ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy); - CGF.EmitCallOrInvoke(ExceptionThrowFn, ExceptionAsObject); + llvm::CallSite Throw = + CGF.EmitCallOrInvoke(ExceptionThrowFn, ExceptionAsObject); + Throw.setDoesNotReturn(); CGF.Builder.CreateUnreachable(); CGF.Builder.ClearInsertionPoint(); } |