From: Daniel Dunbar Date: Wed, 13 Aug 2008 00:59:25 +0000 (+0000) Subject: Change ObjCRuntime GenerateProtocol[Ref] methods to take X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=af2f62ce32e462f256855cd24b06dec4755d2827;p=clang Change ObjCRuntime GenerateProtocol[Ref] methods to take ObjCProtocolDecl directly. Implement CodeGen support for forward protocol decls (no-ops are so nice to implement). Also moved CGObjCRuntime.h out of CodeGenModule.h git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54709 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 89f552225c..6bfd5cb309 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -13,6 +13,7 @@ #include "CodeGenFunction.h" #include "CodeGenModule.h" +#include "CGObjCRuntime.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "llvm/Target/TargetData.h" diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 3d530e8210..12620e7101 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -13,6 +13,7 @@ #include "CodeGenFunction.h" #include "CodeGenModule.h" +#include "CGObjCRuntime.h" #include "clang/AST/ASTContext.h" #include "clang/AST/StmtVisitor.h" #include "llvm/Constants.h" diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 301f693548..ff7a20aea7 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -13,6 +13,7 @@ #include "CodeGenFunction.h" #include "CodeGenModule.h" +#include "CGObjCRuntime.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/StmtVisitor.h" @@ -509,7 +510,7 @@ Value *ScalarExprEmitter::VisitObjCSelectorExpr(ObjCSelectorExpr *E) { Value *ScalarExprEmitter::VisitObjCProtocolExpr(ObjCProtocolExpr *E) { // FIXME: This should pass the Decl not the name. - return Runtime->GenerateProtocolRef(Builder, E->getProtocol()->getName()); + return Runtime->GenerateProtocolRef(Builder, E->getProtocol()); } Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 54aca0c96d..61552c4505 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -18,6 +18,7 @@ #include "CodeGenModule.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" #include "llvm/Module.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/IRBuilder.h" @@ -137,13 +138,8 @@ public: const llvm::SmallVectorImpl &ClassMethodTypes, const llvm::SmallVectorImpl &Protocols); virtual llvm::Value *GenerateProtocolRef(llvm::IRBuilder<> &Builder, - const char *ProtocolName); - virtual void GenerateProtocol(const char *ProtocolName, - const llvm::SmallVectorImpl &Protocols, - const llvm::SmallVectorImpl &InstanceMethodNames, - const llvm::SmallVectorImpl &InstanceMethodTypes, - const llvm::SmallVectorImpl &ClassMethodNames, - const llvm::SmallVectorImpl &ClassMethodTypes); + const ObjCProtocolDecl *PD); + virtual void GenerateProtocol(const ObjCProtocolDecl *PD); virtual llvm::Function *ModuleInitFunction(); }; } // end anonymous namespace @@ -566,17 +562,39 @@ llvm::Constant *CGObjCGNU::GenerateProtocolList( return MakeGlobal(ProtocolListTy, Elements, ".objc_protocol_list"); } -llvm::Value *CGObjCGNU::GenerateProtocolRef(llvm::IRBuilder<> &Builder, const - char *ProtocolName) { - return ExistingProtocols[ProtocolName]; +llvm::Value *CGObjCGNU::GenerateProtocolRef(llvm::IRBuilder<> &Builder, + const ObjCProtocolDecl *PD) { + return ExistingProtocols[PD->getName()]; } -void CGObjCGNU::GenerateProtocol(const char *ProtocolName, - const llvm::SmallVectorImpl &Protocols, - const llvm::SmallVectorImpl &InstanceMethodNames, - const llvm::SmallVectorImpl &InstanceMethodTypes, - const llvm::SmallVectorImpl &ClassMethodNames, - const llvm::SmallVectorImpl &ClassMethodTypes) { +void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { + ASTContext &Context = CGM.getContext(); + const char *ProtocolName = PD->getName(); + llvm::SmallVector Protocols; + for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(), + E = PD->protocol_end(); PI != E; ++PI) + Protocols.push_back((*PI)->getName()); + llvm::SmallVector InstanceMethodNames; + llvm::SmallVector InstanceMethodTypes; + for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(), + E = PD->instmeth_end(); iter != E; iter++) { + std::string TypeStr; + Context.getObjCEncodingForMethodDecl(*iter, TypeStr); + InstanceMethodNames.push_back( + CGM.GetAddrOfConstantString((*iter)->getSelector().getName())); + InstanceMethodTypes.push_back(CGM.GetAddrOfConstantString(TypeStr)); + } + // Collect information about class methods: + llvm::SmallVector ClassMethodNames; + llvm::SmallVector ClassMethodTypes; + for (ObjCProtocolDecl::classmeth_iterator iter = PD->classmeth_begin(), + endIter = PD->classmeth_end() ; iter != endIter ; iter++) { + std::string TypeStr; + Context.getObjCEncodingForMethodDecl((*iter),TypeStr); + ClassMethodNames.push_back( + CGM.GetAddrOfConstantString((*iter)->getSelector().getName())); + ClassMethodTypes.push_back(CGM.GetAddrOfConstantString(TypeStr)); + } llvm::Constant *ProtocolList = GenerateProtocolList(Protocols); llvm::Constant *InstanceMethodList = diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index bd51089903..f6e3207887 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -168,14 +168,9 @@ public: const llvm::SmallVectorImpl &Protocols); virtual llvm::Value *GenerateProtocolRef(llvm::IRBuilder<> &Builder, - const char *ProtocolName); + const ObjCProtocolDecl *PD); - virtual void GenerateProtocol(const char *ProtocolName, - const llvm::SmallVectorImpl &Protocols, - const llvm::SmallVectorImpl &InstanceMethodNames, - const llvm::SmallVectorImpl &InstanceMethodTypes, - const llvm::SmallVectorImpl &ClassMethodNames, - const llvm::SmallVectorImpl &ClassMethodTypes); + virtual void GenerateProtocol(const ObjCProtocolDecl *PD); virtual llvm::Function *ModuleInitFunction(); }; @@ -300,18 +295,13 @@ llvm::Value *CGObjCMac::GenerateMessageSend(llvm::IRBuilder<> &Builder, } llvm::Value *CGObjCMac::GenerateProtocolRef(llvm::IRBuilder<> &Builder, - const char *ProtocolName) { + const ObjCProtocolDecl *PD) { // assert(0 && "Cannot get protocol reference on Mac runtime."); return llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy); return 0; } -void CGObjCMac::GenerateProtocol(const char *ProtocolName, - const llvm::SmallVectorImpl &Protocols, - const llvm::SmallVectorImpl &InstanceMethodNames, - const llvm::SmallVectorImpl &InstanceMethodTypes, - const llvm::SmallVectorImpl &ClassMethodNames, - const llvm::SmallVectorImpl &ClassMethodTypes) { +void CGObjCMac::GenerateProtocol(const ObjCProtocolDecl *PD) { // assert(0 && "Cannot generate protocol for Mac runtime."); } diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h index 07301b50dc..a354aa19c2 100644 --- a/lib/CodeGen/CGObjCRuntime.h +++ b/lib/CodeGen/CGObjCRuntime.h @@ -29,8 +29,9 @@ namespace llvm { } namespace clang { + class ObjCProtocolDecl; class Selector; - + namespace CodeGen { class CodeGenModule; @@ -51,14 +52,18 @@ public: Selector Sel, llvm::Value** ArgV, unsigned ArgC) =0; + /// Generate the function required to register all Objective-C components in /// this compilation unit with the runtime library. virtual llvm::Function *ModuleInitFunction() =0; + /// Get a selector for the specified name and type values virtual llvm::Value *GetSelector(BuilderType &Builder, Selector Sel) =0; + /// Generate a constant string object virtual llvm::Constant *GenerateConstantString(const std::string &String) = 0; + /// Generate a category. A category contains a list of methods (and /// accompanying metadata) and a list of protocols. virtual void GenerateCategory(const char *ClassName, const char *CategoryName, @@ -67,6 +72,7 @@ public: const llvm::SmallVectorImpl &ClassMethodSels, const llvm::SmallVectorImpl &ClassMethodTypes, const llvm::SmallVectorImpl &Protocols) =0; + /// Generate a class stucture for this class. virtual void GenerateClass( const char *ClassName, @@ -80,6 +86,7 @@ public: const llvm::SmallVectorImpl &ClassMethodSels, const llvm::SmallVectorImpl &ClassMethodTypes, const llvm::SmallVectorImpl &Protocols) =0; + virtual llvm::Value *GenerateMessageSendSuper(llvm::IRBuilder &Builder, const llvm::Type *ReturnTy, const char *SuperClassName, @@ -91,16 +98,12 @@ public: /// Emit the code to return the named protocol as an object, as in a /// @protocol expression. virtual llvm::Value *GenerateProtocolRef(llvm::IRBuilder &Builder, - const char *ProtocolName) = 0; + const ObjCProtocolDecl *PD) = 0; /// Generate the named protocol. Protocols contain method metadata but no /// implementations. - virtual void GenerateProtocol(const char *ProtocolName, - const llvm::SmallVectorImpl &Protocols, - const llvm::SmallVectorImpl &InstanceMethodNames, - const llvm::SmallVectorImpl &InstanceMethodTypes, - const llvm::SmallVectorImpl &ClassMethodNames, - const llvm::SmallVectorImpl &ClassMethodTypes) =0; + virtual void GenerateProtocol(const ObjCProtocolDecl *PD) = 0; + /// Generate a function preamble for a method with the specified types virtual llvm::Function *MethodPreamble( const std::string &ClassName, @@ -112,9 +115,11 @@ public: unsigned ArgC, bool isClassMethod, bool isVarArg) = 0; + /// Look up the class for the specified name virtual llvm::Value *LookupClass(BuilderType &Builder, llvm::Value *ClassName) =0; + /// If instance variable addresses are determined at runtime then this should /// return true, otherwise instance variables will be accessed directly from /// the structure. If this returns true then @defs is invalid for this diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 633b7b8dad..f575300b6d 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -14,6 +14,7 @@ #include "CGDebugInfo.h" #include "CodeGenModule.h" #include "CodeGenFunction.h" +#include "CGObjCRuntime.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/Basic/Diagnostic.h" @@ -247,33 +248,7 @@ void CodeGenModule::EmitObjCMethod(const ObjCMethodDecl *OMD) { CodeGenFunction(*this).GenerateObjCMethod(OMD); } void CodeGenModule::EmitObjCProtocolImplementation(const ObjCProtocolDecl *PD){ - llvm::SmallVector Protocols; - for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(), - E = PD->protocol_end(); PI != E; ++PI) - Protocols.push_back((*PI)->getName()); - llvm::SmallVector InstanceMethodNames; - llvm::SmallVector InstanceMethodTypes; - for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(), - E = PD->instmeth_end(); iter != E; iter++) { - std::string TypeStr; - Context.getObjCEncodingForMethodDecl(*iter, TypeStr); - InstanceMethodNames.push_back( - GetAddrOfConstantString((*iter)->getSelector().getName())); - InstanceMethodTypes.push_back(GetAddrOfConstantString(TypeStr)); - } - // Collect information about class methods: - llvm::SmallVector ClassMethodNames; - llvm::SmallVector ClassMethodTypes; - for (ObjCProtocolDecl::classmeth_iterator iter = PD->classmeth_begin(), - endIter = PD->classmeth_end() ; iter != endIter ; iter++) { - std::string TypeStr; - Context.getObjCEncodingForMethodDecl((*iter),TypeStr); - ClassMethodNames.push_back( - GetAddrOfConstantString((*iter)->getSelector().getName())); - ClassMethodTypes.push_back(GetAddrOfConstantString(TypeStr)); - } - Runtime->GenerateProtocol(PD->getName(), Protocols, InstanceMethodNames, - InstanceMethodTypes, ClassMethodNames, ClassMethodTypes); + Runtime->GenerateProtocol(PD); } void CodeGenModule::EmitObjCCategoryImpl(const ObjCCategoryImplDecl *OCD) { diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 3f30cd3283..a837b6369c 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -15,7 +15,6 @@ #define CLANG_CODEGEN_CODEGENMODULE_H #include "CodeGenTypes.h" -#include "CGObjCRuntime.h" #include "clang/AST/Attr.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" @@ -51,6 +50,7 @@ namespace CodeGen { class CodeGenFunction; class CGDebugInfo; + class CGObjCRuntime; /// CodeGenModule - This class organizes the cross-module state that is used /// while generating LLVM code. diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp index affef35f28..17ac0023f8 100644 --- a/lib/CodeGen/ModuleBuilder.cpp +++ b/lib/CodeGen/ModuleBuilder.cpp @@ -72,7 +72,7 @@ namespace { Builder->EmitGlobal(FD); } else if (VarDecl *VD = dyn_cast(D)) { Builder->EmitGlobal(VD); - } else if (isa(D)){ + } else if (isa(D) || isa(D)) { //Forward declaration. Only used for type checking. } else if (ObjCProtocolDecl *PD = dyn_cast(D)){ // Generate Protocol object.