From 29254f4dd114fe2dd5c4e7a261ebea941973ad3d Mon Sep 17 00:00:00 2001 From: David Chisnall Date: Tue, 31 Jan 2012 18:59:20 +0000 Subject: [PATCH] Support @compatibility_alias at run time (GNUstep Runtime) Patch by Niels Grewe! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149401 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGObjCGNU.cpp | 55 ++++++++++++++++++++++++++++++++++- lib/CodeGen/CGObjCMac.cpp | 5 ++++ lib/CodeGen/CGObjCRuntime.h | 3 ++ lib/CodeGen/CodeGenModule.cpp | 2 +- 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 2e7e1c7307..82c478d4fe 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" @@ -288,6 +287,10 @@ private: LazyRuntimeFunction IvarAssignFn, StrongCastAssignFn, MemMoveFn, WeakReadFn, WeakAssignFn, GlobalAssignFn; + typedef std::pair ClassAliasPair; + /// All classes that have aliases set for them. + std::vector ClassAliases; + protected: /// Function used for throwing Objective-C exceptions. LazyRuntimeFunction ExceptionThrowFn; @@ -466,6 +469,7 @@ 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); @@ -1934,6 +1938,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(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(); @@ -2349,6 +2362,46 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { llvm::PointerType::getUnqual(ModuleTy), true); llvm::Value *Register = CGM.CreateRuntimeFunction(FT, "__objc_exec_class"); Builder.CreateCall(Register, Module); + + if (0 != ClassAliases.size()) { + 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::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; diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 3b86c5abb5..3bc595ca44 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -1084,6 +1084,8 @@ public: virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); + virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {}; + virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder, const ObjCProtocolDecl *PD); @@ -1336,6 +1338,9 @@ public: 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); diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h index 3e0c047d06..39523c98a6 100644 --- a/lib/CodeGen/CGObjCRuntime.h +++ b/lib/CodeGen/CGObjCRuntime.h @@ -140,6 +140,9 @@ public: /// Generate a class structure for this class. virtual void GenerateClass(const ObjCImplementationDecl *OID) = 0; + /// Register an class alias. + virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) = 0; + /// Generate an Objective-C message send operation. /// /// \param Method - The method being called, this may be null if synthesizing diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 196ab5dd39..576209f366 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -2421,7 +2421,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { break; } case Decl::ObjCCompatibleAlias: - // compatibility-alias is a directive and has no code gen. + ObjCRuntime->RegisterAlias(cast(D)); break; case Decl::LinkageSpec: -- 2.40.0