diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp | 97 |
1 files changed, 60 insertions, 37 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp index db0bd95..6d129d0 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGObjCGNU.cpp @@ -99,8 +99,8 @@ class LazyRuntimeFunction { /// GNU Objective-C runtime code generation. This class implements the parts of -/// Objective-C support that are specific to the GNU family of runtimes (GCC and -/// GNUstep). +/// Objective-C support that are specific to the GNU family of runtimes (GCC, +/// GNUstep and ObjFW). class CGObjCGNU : public CGObjCRuntime { protected: /// The LLVM module into which output is inserted @@ -292,8 +292,8 @@ private: protected: /// Function used for throwing Objective-C exceptions. LazyRuntimeFunction ExceptionThrowFn; - /// Function used for rethrowing exceptions, used at the end of @finally or - /// @synchronize blocks. + /// Function used for rethrowing exceptions, used at the end of \@finally or + /// \@synchronize blocks. LazyRuntimeFunction ExceptionReThrowFn; /// Function called when entering a catch function. This is required for /// differentiating Objective-C exceptions and foreign exceptions. @@ -301,9 +301,9 @@ protected: /// Function called when exiting from a catch block. Used to do exception /// cleanup. LazyRuntimeFunction ExitCatchFn; - /// Function called when entering an @synchronize block. Acquires the lock. + /// Function called when entering an \@synchronize block. Acquires the lock. LazyRuntimeFunction SyncEnterFn; - /// Function called when exiting an @synchronize block. Releases the lock. + /// Function called when exiting an \@synchronize block. Releases the lock. LazyRuntimeFunction SyncExitFn; private: @@ -350,7 +350,7 @@ private: ArrayRef<Selector> MethodSels, ArrayRef<llvm::Constant *> MethodTypes, bool isClassMethodList); - /// Emits an empty protocol. This is used for @protocol() where no protocol + /// 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 /// real protocol. llvm::Constant *GenerateEmptyProtocol(const std::string &ProtocolName); @@ -397,11 +397,11 @@ private: const ObjCIvarDecl *Ivar); /// Emits a reference to a class. This allows the linker to object if there /// is no class of the matching name. +protected: void EmitClassRef(const std::string &className); /// Emits a pointer to the named class - llvm::Value *GetClassNamed(CGBuilderTy &Builder, const std::string &Name, - bool isWeak); -protected: + virtual llvm::Value *GetClassNamed(CGBuilderTy &Builder, + const std::string &Name, bool isWeak); /// Looks up the method for sending a message to the specified object. This /// mechanism differs between the GCC and GNU runtimes, so this method must be /// overridden in subclasses. @@ -653,6 +653,33 @@ 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. + virtual llvm::Value *GetClassNamed(CGBuilderTy &Builder, + const std::string &Name, bool isWeak) { + if (isWeak) + return CGObjCGNU::GetClassNamed(Builder, Name, isWeak); + + EmitClassRef(Name); + + std::string SymbolName = "_OBJC_CLASS_" + Name; + + llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(SymbolName); + + if (!ClassSymbol) + ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false, + llvm::GlobalValue::ExternalLinkage, + 0, SymbolName); + + return ClassSymbol; + } + +public: + CGObjCObjFW(CodeGenModule &Mod): CGObjCGCC(Mod) {} +}; } // end anonymous namespace @@ -889,7 +916,7 @@ llvm::Constant *CGObjCGNU::GetEHType(QualType T) { // 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().ObjCNonFragileABI) { + if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) { return MakeConstantString("@id"); } else { return 0; @@ -1627,7 +1654,7 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { iter = PD->prop_begin(), endIter = PD->prop_end(); iter != endIter ; iter++) { std::vector<llvm::Constant*> Fields; - ObjCPropertyDecl *property = (*iter); + ObjCPropertyDecl *property = *iter; Fields.push_back(MakeConstantString(property->getNameAsString())); Fields.push_back(llvm::ConstantInt::get(Int8Ty, @@ -1877,7 +1904,7 @@ llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OI iter = OID->propimpl_begin(), endIter = OID->propimpl_end(); iter != endIter ; iter++) { std::vector<llvm::Constant*> Fields; - ObjCPropertyDecl *property = (*iter)->getPropertyDecl(); + ObjCPropertyDecl *property = iter->getPropertyDecl(); ObjCPropertyImplDecl *propertyImpl = *iter; bool isSynthesized = (propertyImpl->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); @@ -1984,7 +2011,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().ObjCNonFragileABI) { + if (CGM.getContext().getLangOpts().ObjCRuntime.isNonFragile()) { instanceSize = 0 - (instanceSize - superInstanceSize); } @@ -1999,7 +2026,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().ObjCNonFragileABI) { + if (CGM.getContext().getLangOpts().ObjCRuntime.isNonFragile()) { Offset = BaseOffset - superInstanceSize; } llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset); @@ -2486,25 +2513,8 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF, ExceptionAsObject = CGF.ObjCEHValueStack.back(); } ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy); - - // Note: This may have to be an invoke, if we want to support constructs like: - // @try { - // @throw(obj); - // } - // @catch(id) ... - // - // This is effectively turning @throw into an incredibly-expensive goto, but - // it may happen as a result of inlining followed by missed optimizations, or - // as a result of stupidity. - llvm::BasicBlock *UnwindBB = CGF.getInvokeDest(); - if (!UnwindBB) { - CGF.Builder.CreateCall(ExceptionThrowFn, ExceptionAsObject); - CGF.Builder.CreateUnreachable(); - } else { - CGF.Builder.CreateInvoke(ExceptionThrowFn, UnwindBB, UnwindBB, - ExceptionAsObject); - } - // Clear the insertion point to indicate we are in unreachable code. + CGF.EmitCallOrInvoke(ExceptionThrowFn, ExceptionAsObject); + CGF.Builder.CreateUnreachable(); CGF.Builder.ClearInsertionPoint(); } @@ -2640,7 +2650,7 @@ static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context, llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF, const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar) { - if (CGM.getLangOpts().ObjCNonFragileABI) { + if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) { Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar); if (RuntimeVersion < 10) return CGF.Builder.CreateZExtOrBitCast( @@ -2665,7 +2675,20 @@ llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF, CGObjCRuntime * clang::CodeGen::CreateGNUObjCRuntime(CodeGenModule &CGM) { - if (CGM.getLangOpts().ObjCNonFragileABI) + switch (CGM.getLangOpts().ObjCRuntime.getKind()) { + case ObjCRuntime::GNUstep: return new CGObjCGNUstep(CGM); - return new CGObjCGCC(CGM); + + case ObjCRuntime::GCC: + return new CGObjCGCC(CGM); + + case ObjCRuntime::ObjFW: + return new CGObjCObjFW(CGM); + + case ObjCRuntime::FragileMacOSX: + case ObjCRuntime::MacOSX: + case ObjCRuntime::iOS: + llvm_unreachable("these runtimes are not GNU runtimes"); + } + llvm_unreachable("bad runtime"); } |