diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGObjC.cpp | 28 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjCGNU.cpp | 208 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjCMac.cpp | 80 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjCRuntime.h | 78 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 123 |
5 files changed, 206 insertions, 311 deletions
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 2e400f4d2ae..df3226d128a 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -103,33 +103,7 @@ llvm::Value *CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { /// Generate an Objective-C method. An Objective-C method is a C function with /// its pointer, name, and types registered in the class struture. void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) { - - llvm::SmallVector<const llvm::Type *, 16> ParamTypes; - for (unsigned i=0 ; i<OMD->param_size() ; i++) { - const llvm::Type *Ty = ConvertType(OMD->getParamDecl(i)->getType()); - if (Ty->isFirstClassType()) - ParamTypes.push_back(Ty); - else - ParamTypes.push_back(llvm::PointerType::getUnqual(Ty)); - } - std::string CategoryName = ""; - if (ObjCCategoryImplDecl *OCD = - dyn_cast<ObjCCategoryImplDecl>(OMD->getMethodContext())) { - CategoryName = OCD->getName(); - } - const llvm::Type *ReturnTy = - CGM.getTypes().ConvertReturnType(OMD->getResultType()); - CurFn = CGM.getObjCRuntime().MethodPreamble( - OMD->getClassInterface()->getName(), - CategoryName, - OMD->getSelector().getName(), - ReturnTy, - llvm::PointerType::getUnqual( - llvm::Type::Int32Ty), - ParamTypes.begin(), - OMD->param_size(), - !OMD->isInstance(), - OMD->isVariadic()); + CurFn = CGM.getObjCRuntime().GenerateMethod(OMD); llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("entry", CurFn); // Create a marker to make it easy to insert allocas into the entryblock diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index c4d236b54d4..4c678c9f8fb 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -20,10 +20,11 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "llvm/Module.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/IRBuilder.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Target/TargetData.h" #include <map> using namespace clang; using llvm::dyn_cast; @@ -109,34 +110,9 @@ public: llvm::Value *ClassName); virtual llvm::Value *GetSelector(llvm::IRBuilder<> &Builder, Selector Sel); - virtual llvm::Function *MethodPreamble( - const std::string &ClassName, - const std::string &CategoryName, - const std::string &MethodName, - const llvm::Type *ReturnTy, - const llvm::Type *SelfTy, - const llvm::Type **ArgTy, - unsigned ArgC, - bool isClassMethod, - bool isVarArg); - virtual void GenerateCategory(const char *ClassName, const char *CategoryName, - const llvm::SmallVectorImpl<Selector> &InstanceMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodTypes, - const llvm::SmallVectorImpl<Selector> &ClassMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodTypes, - const llvm::SmallVectorImpl<std::string> &Protocols); - virtual void GenerateClass( - const char *ClassName, - const char *SuperClassName, - const int instanceSize, - const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames, - const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes, - const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets, - const llvm::SmallVectorImpl<Selector> &InstanceMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodTypes, - const llvm::SmallVectorImpl<Selector> &ClassMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodTypes, - const llvm::SmallVectorImpl<std::string> &Protocols); + virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD); + virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); + virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); virtual llvm::Value *GenerateProtocolRef(llvm::IRBuilder<> &Builder, const ObjCProtocolDecl *PD); virtual void GenerateProtocol(const ObjCProtocolDecl *PD); @@ -623,14 +599,39 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { ".objc_protocol"), IdTy); } -void CGObjCGNU::GenerateCategory( - const char *ClassName, - const char *CategoryName, - const llvm::SmallVectorImpl<Selector> &InstanceMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodTypes, - const llvm::SmallVectorImpl<Selector> &ClassMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodTypes, - const llvm::SmallVectorImpl<std::string> &Protocols) { +void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) { + const char *ClassName = OCD->getClassInterface()->getName(); + const char *CategoryName = OCD->getName(); + // Collect information about instance methods + llvm::SmallVector<Selector, 16> InstanceMethodSels; + llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes; + for (ObjCCategoryDecl::instmeth_iterator iter = OCD->instmeth_begin(), + endIter = OCD->instmeth_end() ; iter != endIter ; iter++) { + InstanceMethodSels.push_back((*iter)->getSelector()); + std::string TypeStr; + CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr); + InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr)); + } + + // Collect information about class methods + llvm::SmallVector<Selector, 16> ClassMethodSels; + llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes; + for (ObjCCategoryDecl::classmeth_iterator iter = OCD->classmeth_begin(), + endIter = OCD->classmeth_end() ; iter != endIter ; iter++) { + ClassMethodSels.push_back((*iter)->getSelector()); + std::string TypeStr; + CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr); + ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr)); + } + + // Collect the names of referenced protocols + llvm::SmallVector<std::string, 16> Protocols; + const ObjCInterfaceDecl *ClassDecl = OCD->getClassInterface(); + const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols(); + for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(), + E = Protos.end(); I != E; ++I) + Protocols.push_back((*I)->getName()); + std::vector<llvm::Constant*> Elements; Elements.push_back(MakeConstantString(CategoryName)); Elements.push_back(MakeConstantString(ClassName)); @@ -649,18 +650,89 @@ void CGObjCGNU::GenerateCategory( MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy)); } -void CGObjCGNU::GenerateClass( - const char *ClassName, - const char *SuperClassName, - const int instanceSize, - const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames, - const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes, - const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets, - const llvm::SmallVectorImpl<Selector> &InstanceMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodTypes, - const llvm::SmallVectorImpl<Selector> &ClassMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodTypes, - const llvm::SmallVectorImpl<std::string> &Protocols) { + +void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { + ASTContext &Context = CGM.getContext(); + + // Get the superclass name. + const ObjCInterfaceDecl * SuperClassDecl = + OID->getClassInterface()->getSuperClass(); + const char * SuperClassName = NULL; + if (SuperClassDecl) { + SuperClassName = SuperClassDecl->getName(); + } + + // Get the class name + ObjCInterfaceDecl * ClassDecl = (ObjCInterfaceDecl*)OID->getClassInterface(); + const char * ClassName = ClassDecl->getName(); + + // Get the size of instances. For runtimes that support late-bound instances + // this should probably be something different (size just of instance + // varaibles in this class, not superclasses?). + int instanceSize = 0; + const llvm::Type *ObjTy = 0; + if (!LateBoundIVars()) { + ObjTy = CGM.getTypes().ConvertType(Context.getObjCInterfaceType(ClassDecl)); + instanceSize = CGM.getTargetData().getABITypeSize(ObjTy); + } else { + // This is required by newer ObjC runtimes. + assert(0 && "Late-bound instance variables not yet supported"); + } + + // Collect information about instance variables. + llvm::SmallVector<llvm::Constant*, 16> IvarNames; + llvm::SmallVector<llvm::Constant*, 16> IvarTypes; + llvm::SmallVector<llvm::Constant*, 16> IvarOffsets; + const llvm::StructLayout *Layout = + CGM.getTargetData().getStructLayout(cast<llvm::StructType>(ObjTy)); + ObjTy = llvm::PointerType::getUnqual(ObjTy); + for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(), + endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) { + // Store the name + IvarNames.push_back(CGM.GetAddrOfConstantCString((*iter)->getName())); + // Get the type encoding for this ivar + std::string TypeStr; + llvm::SmallVector<const RecordType *, 8> EncodingRecordTypes; + Context.getObjCEncodingForType((*iter)->getType(), TypeStr, + EncodingRecordTypes); + IvarTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr)); + // Get the offset + int offset = + (int)Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(*iter)); + IvarOffsets.push_back( + llvm::ConstantInt::get(llvm::Type::Int32Ty, offset)); + } + + // Collect information about instance methods + llvm::SmallVector<Selector, 16> InstanceMethodSels; + llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes; + for (ObjCImplementationDecl::instmeth_iterator iter = OID->instmeth_begin(), + endIter = OID->instmeth_end() ; iter != endIter ; iter++) { + InstanceMethodSels.push_back((*iter)->getSelector()); + std::string TypeStr; + Context.getObjCEncodingForMethodDecl((*iter),TypeStr); + InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr)); + } + + // Collect information about class methods + llvm::SmallVector<Selector, 16> ClassMethodSels; + llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes; + for (ObjCImplementationDecl::classmeth_iterator iter = OID->classmeth_begin(), + endIter = OID->classmeth_end() ; iter != endIter ; iter++) { + ClassMethodSels.push_back((*iter)->getSelector()); + std::string TypeStr; + Context.getObjCEncodingForMethodDecl((*iter),TypeStr); + ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr)); + } + // Collect the names of referenced protocols + llvm::SmallVector<std::string, 16> Protocols; + const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols(); + for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(), + E = Protos.end(); I != E; ++I) + Protocols.push_back((*I)->getName()); + + + // Get the superclass pointer. llvm::Constant *SuperClass; if (SuperClassName) { @@ -834,16 +906,30 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { Builder.CreateRetVoid(); return LoadFunction; } -llvm::Function *CGObjCGNU::MethodPreamble( - const std::string &ClassName, - const std::string &CategoryName, - const std::string &MethodName, - const llvm::Type *ReturnTy, - const llvm::Type *SelfTy, - const llvm::Type **ArgTy, - unsigned ArgC, - bool isClassMethod, - bool isVarArg) { + +llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD) { + const llvm::Type *ReturnTy = + CGM.getTypes().ConvertReturnType(OMD->getResultType()); + const ObjCCategoryImplDecl *OCD = + dyn_cast<ObjCCategoryImplDecl>(OMD->getMethodContext()); + const std::string &CategoryName = OCD ? OCD->getName() : ""; + const llvm::Type *SelfTy = llvm::PointerType::getUnqual(llvm::Type::Int32Ty); + const std::string &ClassName = OMD->getClassInterface()->getName(); + const std::string &MethodName = OMD->getSelector().getName(); + unsigned ArgC = OMD->param_size(); + bool isClassMethod = !OMD->isInstance(); + bool isVarArg = OMD->isVariadic(); + + llvm::SmallVector<const llvm::Type *, 16> ArgTy; + for (unsigned i=0 ; i<OMD->param_size() ; i++) { + const llvm::Type *Ty = + CGM.getTypes().ConvertType(OMD->getParamDecl(i)->getType()); + if (Ty->isFirstClassType()) + ArgTy.push_back(Ty); + else + ArgTy.push_back(llvm::PointerType::getUnqual(Ty)); + } + std::vector<const llvm::Type*> Args; if (!ReturnTy->isSingleValueType() && ReturnTy != llvm::Type::VoidTy) { Args.push_back(llvm::PointerType::getUnqual(ReturnTy)); @@ -851,7 +937,7 @@ llvm::Function *CGObjCGNU::MethodPreamble( } Args.push_back(SelfTy); Args.push_back(SelectorTy); - Args.insert(Args.end(), ArgTy, ArgTy+ArgC); + Args.insert(Args.end(), ArgTy.begin(), ArgTy.begin()+ArgC); llvm::FunctionType *MethodTy = llvm::FunctionType::get(ReturnTy, Args, diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 1db7e01c930..b307148955d 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -218,35 +218,11 @@ public: virtual llvm::Value *GetSelector(llvm::IRBuilder<> &Builder, Selector Sel); - virtual llvm::Function *MethodPreamble(const std::string &ClassName, - const std::string &CategoryName, - const std::string &MethodName, - const llvm::Type *ReturnTy, - const llvm::Type *SelfTy, - const llvm::Type **ArgTy, - unsigned ArgC, - bool isClassMethod, - bool isVarArg); - - virtual void GenerateCategory(const char *ClassName, const char *CategoryName, - const llvm::SmallVectorImpl<Selector> &InstanceMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodTypes, - const llvm::SmallVectorImpl<Selector> &ClassMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodTypes, - const llvm::SmallVectorImpl<std::string> &Protocols); - - virtual void GenerateClass( - const char *ClassName, - const char *SuperClassName, - const int instanceSize, - const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames, - const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes, - const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets, - const llvm::SmallVectorImpl<Selector> &InstanceMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodTypes, - const llvm::SmallVectorImpl<Selector> &ClassMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodTypes, - const llvm::SmallVectorImpl<std::string> &Protocols); + virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD); + + virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); + + virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); virtual llvm::Value *GenerateProtocolRef(llvm::IRBuilder<> &Builder, const ObjCProtocolDecl *PD); @@ -370,7 +346,17 @@ llvm::Value *CGObjCMac::GenerateMessageSend(llvm::IRBuilder<> &Builder, Args[0] = Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp"); Args[1] = EmitSelector(Builder, Sel); std::copy(ArgV, ArgV+ArgC, Args+2); - llvm::CallInst *CI = Builder.CreateCall(F, Args, Args+ArgC+2, "tmp"); + + std::vector<const llvm::Type*> Params; + Params.push_back(ObjCTypes.ObjectPtrTy); + Params.push_back(ObjCTypes.SelectorPtrTy); + llvm::FunctionType *CallFTy = llvm::FunctionType::get(ReturnTy, + Params, + true); + llvm::Type *PCallFTy = llvm::PointerType::getUnqual(CallFTy); + llvm::Constant *C = llvm::ConstantExpr::getBitCast(F, PCallFTy); + llvm::CallInst *CI = Builder.CreateCall(C, + Args, Args+ArgC+2, "tmp"); delete[] Args; return Builder.CreateBitCast(CI, ReturnTy, "tmp"); } @@ -613,29 +599,11 @@ llvm::Constant *CGObjCMac::EmitMethodList(const std::string &TypeName, ObjCTypes.MethodDescriptionListPtrTy); } -void CGObjCMac::GenerateCategory( - const char *ClassName, - const char *CategoryName, - const llvm::SmallVectorImpl<Selector> &InstanceMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodTypes, - const llvm::SmallVectorImpl<Selector> &ClassMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodTypes, - const llvm::SmallVectorImpl<std::string> &Protocols) { +void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { assert(0 && "Cannot generate category for Mac runtime."); } -void CGObjCMac::GenerateClass( - const char *ClassName, - const char *SuperClassName, - const int instanceSize, - const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames, - const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes, - const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets, - const llvm::SmallVectorImpl<Selector> &InstanceMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodTypes, - const llvm::SmallVectorImpl<Selector> &ClassMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodTypes, - const llvm::SmallVectorImpl<std::string> &Protocols) { +void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ClassDecl) { assert(0 && "Cannot generate class for Mac runtime."); } @@ -646,15 +614,7 @@ llvm::Function *CGObjCMac::ModuleInitFunction() { return NULL; } -llvm::Function *CGObjCMac::MethodPreamble(const std::string &ClassName, - const std::string &CategoryName, - const std::string &MethodName, - const llvm::Type *ReturnTy, - const llvm::Type *SelfTy, - const llvm::Type **ArgTy, - unsigned ArgC, - bool isClassMethod, - bool isVarArg) { +llvm::Function *CGObjCMac::GenerateMethod(const ObjCMethodDecl *OMD) { assert(0 && "Cannot generate method preamble for Mac runtime."); return 0; } @@ -724,7 +684,7 @@ void CGObjCMac::EmitModuleInfo() { std::vector<llvm::Constant*> Values(4); Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion); Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size); - // FIXME: GCC just appears to make up an empty name for this? Why? + // This used to be the filename, now it is unused. <rdr://4327263> Values[2] = GetClassName(&CGM.getContext().Idents.get("")); Values[3] = EmitModuleSymbols(); diff --git a/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h index a354aa19c2c..83ca0e638c9 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.h +++ b/clang/lib/CodeGen/CGObjCRuntime.h @@ -29,6 +29,9 @@ namespace llvm { } namespace clang { + class ObjCCategoryImplDecl; + class ObjCImplementationDecl; + class ObjCMethodDecl; class ObjCProtocolDecl; class Selector; @@ -44,49 +47,37 @@ class CGObjCRuntime { public: virtual ~CGObjCRuntime(); - - /// Generate an Objective-C message send operation - virtual llvm::Value *GenerateMessageSend(BuilderType &Builder, - const llvm::Type *ReturnTy, - llvm::Value *Receiver, - 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; + virtual llvm::Function *ModuleInitFunction() = 0; - /// Get a selector for the specified name and type values + /// Get a selector for the specified name and type values. The + /// return value should have the LLVM type for pointer-to + /// ASTContext::getObjCSelType(). virtual llvm::Value *GetSelector(BuilderType &Builder, - Selector Sel) =0; + Selector Sel) = 0; - /// Generate a constant string object + /// 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, - const llvm::SmallVectorImpl<Selector> &InstanceMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodTypes, - const llvm::SmallVectorImpl<Selector> &ClassMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodTypes, - const llvm::SmallVectorImpl<std::string> &Protocols) =0; + virtual void GenerateCategory(const ObjCCategoryImplDecl *OCD) = 0; /// Generate a class stucture for this class. - virtual void GenerateClass( - const char *ClassName, - const char *SuperClassName, - const int instanceSize, - const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames, - const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes, - const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets, - const llvm::SmallVectorImpl<Selector> &InstanceMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &InstanceMethodTypes, - const llvm::SmallVectorImpl<Selector> &ClassMethodSels, - const llvm::SmallVectorImpl<llvm::Constant *> &ClassMethodTypes, - const llvm::SmallVectorImpl<std::string> &Protocols) =0; + virtual void GenerateClass(const ObjCImplementationDecl *OID) = 0; + + /// Generate an Objective-C message send operation. + virtual llvm::Value *GenerateMessageSend(BuilderType &Builder, + const llvm::Type *ReturnTy, + llvm::Value *Receiver, + Selector Sel, + llvm::Value** ArgV, + unsigned ArgC) = 0; + /// Generate an Objective-C message send operation to the super + /// class. virtual llvm::Value *GenerateMessageSendSuper(llvm::IRBuilder<true> &Builder, const llvm::Type *ReturnTy, const char *SuperClassName, @@ -98,27 +89,24 @@ public: /// Emit the code to return the named protocol as an object, as in a /// @protocol expression. virtual llvm::Value *GenerateProtocolRef(llvm::IRBuilder<true> &Builder, - const ObjCProtocolDecl *PD) = 0; + const ObjCProtocolDecl *OPD) = 0; /// Generate the named protocol. Protocols contain method metadata but no /// implementations. - 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, - const std::string &CategoryName, - const std::string &MethodName, - const llvm::Type *ReturnTy, - const llvm::Type *SelfTy, - const llvm::Type **ArgTy, - unsigned ArgC, - bool isClassMethod, - bool isVarArg) = 0; + virtual void GenerateProtocol(const ObjCProtocolDecl *OPD) = 0; + + /// Generate a function preamble for a method with the specified + /// types. + + // FIXME: Current this just generates the Function definition, but + // really this should also be generating the loads of the + // parameters, as the runtime should have full control over how + // parameters are passed. + virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD) = 0; /// Look up the class for the specified name virtual llvm::Value *LookupClass(BuilderType &Builder, - llvm::Value *ClassName) =0; + 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 diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 500bf5b5d54..3340cdff56a 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -252,125 +252,12 @@ void CodeGenModule::EmitObjCProtocolImplementation(const ObjCProtocolDecl *PD){ } void CodeGenModule::EmitObjCCategoryImpl(const ObjCCategoryImplDecl *OCD) { + Runtime->GenerateCategory(OCD); +} - // Collect information about instance methods - llvm::SmallVector<Selector, 16> InstanceMethodSels; - llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes; - for (ObjCCategoryDecl::instmeth_iterator iter = OCD->instmeth_begin(), - endIter = OCD->instmeth_end() ; iter != endIter ; iter++) { - InstanceMethodSels.push_back((*iter)->getSelector()); - std::string TypeStr; - Context.getObjCEncodingForMethodDecl(*iter,TypeStr); - InstanceMethodTypes.push_back(GetAddrOfConstantCString(TypeStr)); - } - - // Collect information about class methods - llvm::SmallVector<Selector, 16> ClassMethodSels; - llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes; - for (ObjCCategoryDecl::classmeth_iterator iter = OCD->classmeth_begin(), - endIter = OCD->classmeth_end() ; iter != endIter ; iter++) { - ClassMethodSels.push_back((*iter)->getSelector()); - std::string TypeStr; - Context.getObjCEncodingForMethodDecl(*iter,TypeStr); - ClassMethodTypes.push_back(GetAddrOfConstantCString(TypeStr)); - } - - // Collect the names of referenced protocols - llvm::SmallVector<std::string, 16> Protocols; - const ObjCInterfaceDecl *ClassDecl = OCD->getClassInterface(); - const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols(); - for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(), - E = Protos.end(); I != E; ++I) - Protocols.push_back((*I)->getName()); - - // Generate the category - Runtime->GenerateCategory(OCD->getClassInterface()->getName(), - OCD->getName(), InstanceMethodSels, InstanceMethodTypes, - ClassMethodSels, ClassMethodTypes, Protocols); -} - -void CodeGenModule::EmitObjCClassImplementation( - const ObjCImplementationDecl *OID) { - // Get the superclass name. - const ObjCInterfaceDecl * SCDecl = OID->getClassInterface()->getSuperClass(); - const char * SCName = NULL; - if (SCDecl) { - SCName = SCDecl->getName(); - } - - // Get the class name - ObjCInterfaceDecl * ClassDecl = (ObjCInterfaceDecl*)OID->getClassInterface(); - const char * ClassName = ClassDecl->getName(); - - // Get the size of instances. For runtimes that support late-bound instances - // this should probably be something different (size just of instance - // varaibles in this class, not superclasses?). - int instanceSize = 0; - const llvm::Type *ObjTy = 0; - if (!Runtime->LateBoundIVars()) { - ObjTy = getTypes().ConvertType(Context.getObjCInterfaceType(ClassDecl)); - instanceSize = TheTargetData.getABITypeSize(ObjTy); - } else { - // This is required by newer ObjC runtimes. - assert(0 && "Late-bound instance variables not yet supported"); - } - - // Collect information about instance variables. - llvm::SmallVector<llvm::Constant*, 16> IvarNames; - llvm::SmallVector<llvm::Constant*, 16> IvarTypes; - llvm::SmallVector<llvm::Constant*, 16> IvarOffsets; - const llvm::StructLayout *Layout = - TheTargetData.getStructLayout(cast<llvm::StructType>(ObjTy)); - ObjTy = llvm::PointerType::getUnqual(ObjTy); - for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(), - endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) { - // Store the name - IvarNames.push_back(GetAddrOfConstantCString((*iter)->getName())); - // Get the type encoding for this ivar - std::string TypeStr; - llvm::SmallVector<const RecordType *, 8> EncodingRecordTypes; - Context.getObjCEncodingForType((*iter)->getType(), TypeStr, - EncodingRecordTypes); - IvarTypes.push_back(GetAddrOfConstantCString(TypeStr)); - // Get the offset - int offset = - (int)Layout->getElementOffset(getTypes().getLLVMFieldNo(*iter)); - IvarOffsets.push_back( - llvm::ConstantInt::get(llvm::Type::Int32Ty, offset)); - } - - // Collect information about instance methods - llvm::SmallVector<Selector, 16> InstanceMethodSels; - llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes; - for (ObjCImplementationDecl::instmeth_iterator iter = OID->instmeth_begin(), - endIter = OID->instmeth_end() ; iter != endIter ; iter++) { - InstanceMethodSels.push_back((*iter)->getSelector()); - std::string TypeStr; - Context.getObjCEncodingForMethodDecl((*iter),TypeStr); - InstanceMethodTypes.push_back(GetAddrOfConstantCString(TypeStr)); - } - - // Collect information about class methods - llvm::SmallVector<Selector, 16> ClassMethodSels; - llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes; - for (ObjCImplementationDecl::classmeth_iterator iter = OID->classmeth_begin(), - endIter = OID->classmeth_end() ; iter != endIter ; iter++) { - ClassMethodSels.push_back((*iter)->getSelector()); - std::string TypeStr; - Context.getObjCEncodingForMethodDecl((*iter),TypeStr); - ClassMethodTypes.push_back(GetAddrOfConstantCString(TypeStr)); - } - // Collect the names of referenced protocols - llvm::SmallVector<std::string, 16> Protocols; - const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols(); - for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(), - E = Protos.end(); I != E; ++I) - Protocols.push_back((*I)->getName()); - - // Generate the category - Runtime->GenerateClass(ClassName, SCName, instanceSize, IvarNames, IvarTypes, - IvarOffsets, InstanceMethodSels, InstanceMethodTypes, - ClassMethodSels, ClassMethodTypes, Protocols); +void +CodeGenModule::EmitObjCClassImplementation(const ObjCImplementationDecl *OID) { + Runtime->GenerateClass(OID); } void CodeGenModule::EmitStatics() { |