/// 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
#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;
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);
".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));
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) {
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));
}
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,
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);
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");
}
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.");
}
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;
}
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();
}
namespace clang {
+ class ObjCCategoryImplDecl;
+ class ObjCImplementationDecl;
+ class ObjCMethodDecl;
class ObjCProtocolDecl;
class Selector;
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,
/// 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
}
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() {