Newer
Older
//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This provides Objective-C code generation targetting the Apple runtime.
//
//===----------------------------------------------------------------------===//
#include "CGObjCRuntime.h"
#include "CodeGenFunction.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "llvm/Target/TargetData.h"
using namespace CodeGen;
typedef std::vector<llvm::Constant*> ConstantVector;
// FIXME: We should find a nicer way to make the labels for
// metadata, string concatenation is lame.
class ObjCCommonTypesHelper {
protected:
CodeGen::CodeGenModule &CGM;
const llvm::Type *ShortTy, *IntTy, *LongTy;
const llvm::Type *Int8PtrTy;
/// ObjectPtrTy - LLVM type for object handles (typeof(id))
const llvm::Type *ObjectPtrTy;
/// PtrObjectPtrTy - LLVM type for id *
const llvm::Type *PtrObjectPtrTy;
/// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
/// ProtocolPtrTy - LLVM type for external protocol handles
/// (typeof(Protocol))
const llvm::Type *ExternalProtocolPtrTy;
// SuperCTy - clang type for struct objc_super.
QualType SuperCTy;
// SuperPtrCTy - clang type for struct objc_super *.
QualType SuperPtrCTy;
/// SuperTy - LLVM type for struct objc_super.
const llvm::StructType *SuperTy;
/// SuperPtrTy - LLVM type for struct objc_super *.
const llvm::Type *SuperPtrTy;
/// PropertyTy - LLVM type for struct objc_property (struct _prop_t
/// in GCC parlance).
const llvm::StructType *PropertyTy;
/// PropertyListTy - LLVM type for struct objc_property_list
/// (_prop_list_t in GCC parlance).
const llvm::StructType *PropertyListTy;
/// PropertyListPtrTy - LLVM type for struct objc_property_list*.
const llvm::Type *PropertyListPtrTy;
// MethodTy - LLVM type for struct objc_method.
const llvm::StructType *MethodTy;
/// CacheTy - LLVM type for struct objc_cache.
const llvm::Type *CacheTy;
/// CachePtrTy - LLVM type for struct objc_cache *.
const llvm::Type *CachePtrTy;
llvm::Function *GetPropertyFn, *SetPropertyFn;
llvm::Function *EnumerationMutationFn;
/// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
llvm::Function *GcReadWeakFn;
/// GcAssignWeakFn -- LLVM objc_assign_weak function.
llvm::Function *GcAssignWeakFn;
/// GcAssignGlobalFn -- LLVM objc_assign_global function.
llvm::Function *GcAssignGlobalFn;
/// GcAssignIvarFn -- LLVM objc_assign_ivar function.
llvm::Function *GcAssignIvarFn;
/// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
llvm::Function *GcAssignStrongCastFn;
/// ExceptionThrowFn - LLVM objc_exception_throw function.
llvm::Function *ExceptionThrowFn;
ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
~ObjCCommonTypesHelper(){}
};
/// ObjCTypesHelper - Helper class that encapsulates lazy
/// construction of varies types used during ObjC generation.
class ObjCTypesHelper : public ObjCCommonTypesHelper {
private:
llvm::Function *MessageSendFn, *MessageSendStretFn, *MessageSendFpretFn;
llvm::Function *MessageSendSuperFn, *MessageSendSuperStretFn,
*MessageSendSuperFpretFn;
public:
/// SymtabTy - LLVM type for struct objc_symtab.
const llvm::StructType *SymtabTy;
/// SymtabPtrTy - LLVM type for struct objc_symtab *.
const llvm::Type *SymtabPtrTy;
/// ModuleTy - LLVM type for struct objc_module.
const llvm::StructType *ModuleTy;
/// ProtocolTy - LLVM type for struct objc_protocol.
const llvm::StructType *ProtocolTy;
/// ProtocolPtrTy - LLVM type for struct objc_protocol *.
const llvm::Type *ProtocolPtrTy;
/// ProtocolExtensionTy - LLVM type for struct
/// objc_protocol_extension.
const llvm::StructType *ProtocolExtensionTy;
/// ProtocolExtensionTy - LLVM type for struct
/// objc_protocol_extension *.
const llvm::Type *ProtocolExtensionPtrTy;
/// MethodDescriptionTy - LLVM type for struct
/// objc_method_description.
const llvm::StructType *MethodDescriptionTy;
/// MethodDescriptionListTy - LLVM type for struct
/// objc_method_description_list.
const llvm::StructType *MethodDescriptionListTy;
/// MethodDescriptionListPtrTy - LLVM type for struct
/// objc_method_description_list *.
const llvm::Type *MethodDescriptionListPtrTy;
/// ProtocolListTy - LLVM type for struct objc_property_list.
const llvm::Type *ProtocolListTy;
/// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
const llvm::Type *ProtocolListPtrTy;
/// CategoryTy - LLVM type for struct objc_category.
const llvm::StructType *CategoryTy;
/// ClassTy - LLVM type for struct objc_class.
const llvm::StructType *ClassTy;
/// ClassPtrTy - LLVM type for struct objc_class *.
const llvm::Type *ClassPtrTy;
/// ClassExtensionTy - LLVM type for struct objc_class_ext.
const llvm::StructType *ClassExtensionTy;
/// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
const llvm::Type *ClassExtensionPtrTy;
// IvarTy - LLVM type for struct objc_ivar.
const llvm::StructType *IvarTy;
/// IvarListTy - LLVM type for struct objc_ivar_list.
const llvm::Type *IvarListTy;
/// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
const llvm::Type *IvarListPtrTy;
/// MethodListTy - LLVM type for struct objc_method_list.
const llvm::Type *MethodListTy;
/// MethodListPtrTy - LLVM type for struct objc_method_list *.
const llvm::Type *MethodListPtrTy;
/// ExceptionDataTy - LLVM type for struct _objc_exception_data.
const llvm::Type *ExceptionDataTy;
/// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
llvm::Function *ExceptionTryEnterFn;
/// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
llvm::Function *ExceptionTryExitFn;
/// ExceptionExtractFn - LLVM objc_exception_extract function.
llvm::Function *ExceptionExtractFn;
/// ExceptionMatchFn - LLVM objc_exception_match function.
llvm::Function *ExceptionMatchFn;
/// SetJmpFn - LLVM _setjmp function.
llvm::Function *SetJmpFn;
/// SyncEnterFn - LLVM object_sync_enter function.
llvm::Function *SyncEnterFn;
/// SyncExitFn - LLVM object_sync_exit function.
llvm::Function *SyncExitFn;
public:
ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
~ObjCTypesHelper() {}
llvm::Function *getSendFn(bool IsSuper) {
return IsSuper ? MessageSendSuperFn : MessageSendFn;
}
llvm::Function *getSendStretFn(bool IsSuper) {
return IsSuper ? MessageSendSuperStretFn : MessageSendStretFn;
}
llvm::Function *getSendFpretFn(bool IsSuper) {
return IsSuper ? MessageSendSuperFpretFn : MessageSendFpretFn;
}
/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
/// modern abi
class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
llvm::Function *MessageSendFixupFn, *MessageSendFpretFixupFn,
*MessageSendStretFixupFn, *MessageSendIdFixupFn,
*MessageSendIdStretFixupFn, *MessageSendSuper2FixupFn,
*MessageSendSuper2StretFixupFn;
// MethodListnfABITy - LLVM for struct _method_list_t
const llvm::StructType *MethodListnfABITy;
// MethodListnfABIPtrTy - LLVM for struct _method_list_t*
const llvm::Type *MethodListnfABIPtrTy;
// ProtocolnfABITy = LLVM for struct _protocol_t
const llvm::StructType *ProtocolnfABITy;
// ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
const llvm::Type *ProtocolnfABIPtrTy;
// ProtocolListnfABITy - LLVM for struct _objc_protocol_list
const llvm::StructType *ProtocolListnfABITy;
// ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
const llvm::Type *ProtocolListnfABIPtrTy;
// ClassnfABITy - LLVM for struct _class_t
const llvm::StructType *ClassnfABITy;
// ClassnfABIPtrTy - LLVM for struct _class_t*
const llvm::Type *ClassnfABIPtrTy;
// IvarnfABITy - LLVM for struct _ivar_t
const llvm::StructType *IvarnfABITy;
// IvarListnfABITy - LLVM for struct _ivar_list_t
const llvm::StructType *IvarListnfABITy;
// IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
const llvm::Type *IvarListnfABIPtrTy;
// ClassRonfABITy - LLVM for struct _class_ro_t
const llvm::StructType *ClassRonfABITy;
// ImpnfABITy - LLVM for id (*)(id, SEL, ...)
const llvm::Type *ImpnfABITy;
// CategorynfABITy - LLVM for struct _category_t
const llvm::StructType *CategorynfABITy;
// New types for nonfragile abi messaging.
// MessageRefTy - LLVM for:
// struct _message_ref_t {
// IMP messenger;
// SEL name;
// };
const llvm::StructType *MessageRefTy;
// MessageRefCTy - clang type for struct _message_ref_t
QualType MessageRefCTy;
// MessageRefPtrTy - LLVM for struct _message_ref_t*
const llvm::Type *MessageRefPtrTy;
// MessageRefCPtrTy - clang type for struct _message_ref_t*
QualType MessageRefCPtrTy;
// MessengerTy - Type of the messenger (shown as IMP above)
const llvm::FunctionType *MessengerTy;
// SuperMessageRefTy - LLVM for:
// struct _super_message_ref_t {
// SUPER_IMP messenger;
// SEL name;
// };
const llvm::StructType *SuperMessageRefTy;
// SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
const llvm::Type *SuperMessageRefPtrTy;
ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
~ObjCNonFragileABITypesHelper(){}
};
class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
protected:
CodeGen::CodeGenModule &CGM;
// FIXME! May not be needing this after all.
/// LazySymbols - Symbols to generate a lazy reference for. See
/// DefinedSymbols and FinishModule().
std::set<IdentifierInfo*> LazySymbols;
/// DefinedSymbols - External symbols which are defined by this
/// module. The symbols in this list and LazySymbols are used to add
/// special linker symbols which ensure that Objective-C modules are
/// linked properly.
std::set<IdentifierInfo*> DefinedSymbols;
/// ClassNames - uniqued class names.
llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
/// MethodVarNames - uniqued method variable names.
llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
/// MethodVarTypes - uniqued method type signatures. We have to use
/// a StringMap here because have no other unique reference.
llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
/// MethodDefinitions - map of methods which have been defined in
/// this translation unit.
llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
/// PropertyNames - uniqued method variable names.
llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
/// ClassReferences - uniqued class references.
llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
/// SelectorReferences - uniqued selector references.
llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
/// Protocols - Protocols for which an objc_protocol structure has
/// been emitted. Forward declarations are handled by creating an
/// empty structure whose initializer is filled in when/if defined.
llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
/// DefinedProtocols - Protocols which have actually been
/// defined. We should not need this, see FIXME in GenerateProtocol.
llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
/// DefinedClasses - List of defined classes.
std::vector<llvm::GlobalValue*> DefinedClasses;
/// DefinedCategories - List of defined categories.
std::vector<llvm::GlobalValue*> DefinedCategories;
/// UsedGlobals - List of globals to pack into the llvm.used metadata
std::vector<llvm::GlobalVariable*> UsedGlobals;
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
/// GetNameForMethod - Return a name for the given method.
/// \param[out] NameOut - The return value.
void GetNameForMethod(const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD,
std::string &NameOut);
/// GetMethodVarName - Return a unique constant for the given
/// selector's name. The return value has type char *.
llvm::Constant *GetMethodVarName(Selector Sel);
llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
llvm::Constant *GetMethodVarName(const std::string &Name);
/// GetMethodVarType - Return a unique constant for the given
/// selector's name. The return value has type char *.
// FIXME: This is a horrible name.
llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
llvm::Constant *GetMethodVarType(const std::string &Name);
/// GetPropertyName - Return a unique constant for the given
/// name. The return value has type char *.
llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
// FIXME: This can be dropped once string functions are unified.
llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
const Decl *Container);
/// GetClassName - Return a unique constant for the given selector's
/// name. The return value has type char *.
llvm::Constant *GetClassName(IdentifierInfo *Ident);
const RecordDecl *GetFirstIvarInRecord(const ObjCInterfaceDecl *OID,
RecordDecl::field_iterator &FIV,
RecordDecl::field_iterator &PIV);
/// EmitPropertyList - Emit the given property list. The return
/// value has type PropertyListPtrTy.
llvm::Constant *EmitPropertyList(const std::string &Name,
const Decl *Container,
const ObjCContainerDecl *OCD,
const ObjCCommonTypesHelper &ObjCTypes);
/// GetProtocolRef - Return a reference to the internal protocol
/// description, creating an empty one if it has not been
/// defined. The return value has type ProtocolPtrTy.
llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
public:
CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : CGM(cgm)
{ }
virtual llvm::Constant *GenerateConstantString(const std::string &String);
virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD=0);
virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
/// GetOrEmitProtocol - Get the protocol object for the given
/// declaration, emitting it if necessary. The return value has type
/// ProtocolPtrTy.
virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
/// GetOrEmitProtocolRef - Get a forward reference to the protocol
/// object for the given declaration, emitting it if needed. These
/// forward references will be filled in with empty bodies if no
/// definition is seen. The return value has type ProtocolPtrTy.
virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
};
class CGObjCMac : public CGObjCCommonMac {
private:
ObjCTypesHelper ObjCTypes;
/// EmitImageInfo - Emit the image info marker used to encode some module
/// level information.
void EmitImageInfo();
/// EmitModuleInfo - Another marker encoding module level
/// information.
void EmitModuleInfo();
/// EmitModuleSymols - Emit module symbols, the list of defined
/// classes and categories. The result has type SymtabPtrTy.
llvm::Constant *EmitModuleSymbols();
/// FinishModule - Write out global data structures at the end of
/// processing a translation unit.
void FinishModule();
/// EmitClassExtension - Generate the class extension structure used
/// to store the weak ivar layout and properties. The return value
/// has type ClassExtensionPtrTy.
llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
/// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
/// for the given class.
llvm::Value *EmitClassRef(CGBuilderTy &Builder,
const ObjCInterfaceDecl *ID);
CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
QualType ResultType,
Selector Sel,
QualType Arg0Ty,
bool IsSuper,
const CallArgList &CallArgs);
/// EmitIvarList - Emit the ivar list for the given
/// implementation. If ForClass is true the list of class ivars
/// (i.e. metaclass ivars) is emitted, otherwise the list of
/// interface ivars will be emitted. The return value has type
/// IvarListPtrTy.
llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
bool ForClass);
/// EmitMetaClass - Emit a forward reference to the class structure
/// for the metaclass of the given interface. The return value has
/// type ClassPtrTy.
llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
/// EmitMetaClass - Emit a class structure for the metaclass of the
/// given implementation. The return value has type ClassPtrTy.
llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
llvm::Constant *Protocols,
const llvm::Type *InterfaceTy,
const ConstantVector &Methods);
llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
/// EmitMethodList - Emit the method list for the given
/// implementation. The return value has type MethodListPtrTy.
llvm::Constant *EmitMethodList(const std::string &Name,
const char *Section,
const ConstantVector &Methods);
/// EmitMethodDescList - Emit a method description list for a list of
/// method declarations.
/// - TypeName: The name for the type containing the methods.
/// - IsProtocol: True iff these methods are for a protocol.
/// - ClassMethds: True iff these are class methods.
/// - Required: When true, only "required" methods are
/// listed. Similarly, when false only "optional" methods are
/// listed. For classes this should always be true.
/// - begin, end: The method list to output.
///
/// The return value has type MethodDescriptionListPtrTy.
llvm::Constant *EmitMethodDescList(const std::string &Name,
const char *Section,
const ConstantVector &Methods);
/// GetOrEmitProtocol - Get the protocol object for the given
/// declaration, emitting it if necessary. The return value has type
/// ProtocolPtrTy.
virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
/// GetOrEmitProtocolRef - Get a forward reference to the protocol
/// object for the given declaration, emitting it if needed. These
/// forward references will be filled in with empty bodies if no
/// definition is seen. The return value has type ProtocolPtrTy.
virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
/// EmitProtocolExtension - Generate the protocol extension
/// structure used to store optional instance and class methods, and
/// protocol properties. The return value has type
/// ProtocolExtensionPtrTy.
llvm::Constant *
EmitProtocolExtension(const ObjCProtocolDecl *PD,
const ConstantVector &OptInstanceMethods,
const ConstantVector &OptClassMethods);
/// EmitProtocolList - Generate the list of referenced
/// protocols. The return value has type ProtocolListPtrTy.
llvm::Constant *EmitProtocolList(const std::string &Name,
ObjCProtocolDecl::protocol_iterator begin,
ObjCProtocolDecl::protocol_iterator end);
/// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
/// for the given selector.
llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel);
CGObjCMac(CodeGen::CodeGenModule &cgm);
virtual llvm::Function *ModuleInitFunction();
virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
QualType ResultType,
Selector Sel,
bool IsClassMessage,
const CallArgList &CallArgs);
virtual CodeGen::RValue
GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
QualType ResultType,
Selector Sel,
const ObjCInterfaceDecl *Class,
llvm::Value *Receiver,
bool IsClassMessage,
const CallArgList &CallArgs);
virtual llvm::Value *GetClass(CGBuilderTy &Builder,
const ObjCInterfaceDecl *ID);
virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel);
virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
const ObjCProtocolDecl *PD);
virtual llvm::Function *GetPropertyGetFunction();
virtual llvm::Function *GetPropertySetFunction();
virtual llvm::Function *EnumerationMutationFunction();
virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
const Stmt &S);
virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
const ObjCAtThrowStmt &S);
virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
llvm::Value *AddrWeakObj);
virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dst);
virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dest);
virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dest);
virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dest);
virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
QualType ObjectTy,
llvm::Value *BaseValue,
const ObjCIvarDecl *Ivar,
const FieldDecl *Field,
unsigned CVRQualifiers);
virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar);
class CGObjCNonFragileABIMac : public CGObjCCommonMac {
ObjCNonFragileABITypesHelper ObjCTypes;
llvm::GlobalVariable* ObjCEmptyCacheVar;
llvm::GlobalVariable* ObjCEmptyVtableVar;
/// MetaClassReferences - uniqued meta class references.
llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
/// FinishNonFragileABIModule - Write out global data structures at the end of
/// processing a translation unit.
void FinishNonFragileABIModule();
llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
unsigned InstanceStart,
unsigned InstanceSize,
const ObjCImplementationDecl *ID);
llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
llvm::Constant *IsAGV,
llvm::Constant *SuperClassGV,
llvm::Constant *ClassRoGV,
bool HiddenVisibility);
llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
/// EmitMethodList - Emit the method list for the given
/// implementation. The return value has type MethodListnfABITy.
llvm::Constant *EmitMethodList(const std::string &Name,
const char *Section,
const ConstantVector &Methods);
/// EmitIvarList - Emit the ivar list for the given
/// implementation. If ForClass is true the list of class ivars
/// (i.e. metaclass ivars) is emitted, otherwise the list of
/// interface ivars will be emitted. The return value has type
/// IvarListnfABIPtrTy.
llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
const ObjCIvarDecl *Ivar,
unsigned long int offset);
/// GetOrEmitProtocol - Get the protocol object for the given
/// declaration, emitting it if necessary. The return value has type
/// ProtocolPtrTy.
virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
/// GetOrEmitProtocolRef - Get a forward reference to the protocol
/// object for the given declaration, emitting it if needed. These
/// forward references will be filled in with empty bodies if no
/// definition is seen. The return value has type ProtocolPtrTy.
virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
/// EmitProtocolList - Generate the list of referenced
/// protocols. The return value has type ProtocolListPtrTy.
llvm::Constant *EmitProtocolList(const std::string &Name,
ObjCProtocolDecl::protocol_iterator begin,
ObjCProtocolDecl::protocol_iterator end);
CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
QualType ResultType,
Selector Sel,
llvm::Value *Receiver,
QualType Arg0Ty,
bool IsSuper,
const CallArgList &CallArgs);
/// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
/// for the given class.
llvm::Value *EmitClassRef(CGBuilderTy &Builder,
const ObjCInterfaceDecl *ID,
bool IsSuper = false);
/// EmitMetaClassRef - Return a Value * of the address of _class_t
/// meta-data
llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
const ObjCInterfaceDecl *ID);
/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
/// the given ivar.
///
llvm::GlobalVariable * ObjCIvarOffsetVariable(std::string &Name,
const ObjCInterfaceDecl *ID,
const ObjCIvarDecl *Ivar);
/// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
/// for the given selector.
llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel);
CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
// FIXME. All stubs for now!
virtual llvm::Function *ModuleInitFunction();
virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
QualType ResultType,
Selector Sel,
llvm::Value *Receiver,
bool IsClassMessage,
const CallArgList &CallArgs);
virtual CodeGen::RValue
GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
QualType ResultType,
Selector Sel,
const ObjCInterfaceDecl *Class,
llvm::Value *Receiver,
bool IsClassMessage,
const CallArgList &CallArgs);
virtual llvm::Value *GetClass(CGBuilderTy &Builder,
const ObjCInterfaceDecl *ID);
virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel)
{ return EmitSelector(Builder, Sel); }
virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
const ObjCProtocolDecl *PD);
virtual llvm::Function *GetPropertyGetFunction(){
return ObjCTypes.GetPropertyFn;
}
virtual llvm::Function *GetPropertySetFunction(){
return ObjCTypes.SetPropertyFn;
}
virtual llvm::Function *EnumerationMutationFunction() {
return ObjCTypes.EnumerationMutationFn;
}
virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
const Stmt &S) {
CGF.ErrorUnsupported(&S, "try or synchronized statement");
}
virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
const ObjCAtThrowStmt &S);
virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
llvm::Value *AddrWeakObj);
virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dst);
virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dest);
virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dest);
virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dest);
virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
QualType ObjectTy,
llvm::Value *BaseValue,
const ObjCIvarDecl *Ivar,
const FieldDecl *Field,
unsigned CVRQualifiers);
virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar);
} // end anonymous namespace
/* *** Helper Functions *** */
/// getConstantGEP() - Help routine to construct simple GEPs.
static llvm::Constant *getConstantGEP(llvm::Constant *C,
unsigned idx0,
unsigned idx1) {
llvm::Value *Idxs[] = {
llvm::ConstantInt::get(llvm::Type::Int32Ty, idx0),
llvm::ConstantInt::get(llvm::Type::Int32Ty, idx1)
};
return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
}
/* *** CGObjCMac Public Interface *** */
CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
ObjCTypes(cgm)
ObjCABI = 1;
/// GetClass - Return a reference to the class for the given interface
/// decl.
llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
const ObjCInterfaceDecl *ID) {
return EmitClassRef(Builder, ID);
}
/// GetSelector - Return the pointer to the unique'd string for this selector.
llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel) {
return EmitSelector(Builder, Sel);
/// Generate a constant CFString object.
/*
struct __builtin_CFString {
const int *isa; // point to __CFConstantStringClassReference
int flags;
const char *str;
long length;
};
*/
llvm::Constant *CGObjCCommonMac::GenerateConstantString(
const std::string &String) {
return CGM.GetAddrOfConstantCFString(String);
}
/// Generates a message send where the super is the receiver. This is
/// a message send to self with special delivery semantics indicating
/// which class's method should be called.
CodeGen::RValue
CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
QualType ResultType,
Selector Sel,
const ObjCInterfaceDecl *Class,
llvm::Value *Receiver,
const CodeGen::CallArgList &CallArgs) {
// Create and init a super structure; this is a (receiver, class)
// pair we will pass to objc_msgSendSuper.
llvm::Value *ObjCSuper =
CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
llvm::Value *ReceiverAsObject =
CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
CGF.Builder.CreateStore(ReceiverAsObject,
CGF.Builder.CreateStructGEP(ObjCSuper, 0));
// If this is a class message the metaclass is passed as the target.
llvm::Value *Target;
if (IsClassMessage) {
llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
Target = Super;
} else {
Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
}
// FIXME: We shouldn't need to do this cast, rectify the ASTContext
// and ObjCTypes types.
const llvm::Type *ClassTy =
CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Target = CGF.Builder.CreateBitCast(Target, ClassTy);
CGF.Builder.CreateStore(Target,
CGF.Builder.CreateStructGEP(ObjCSuper, 1));
return EmitMessageSend(CGF, ResultType, Sel,
ObjCSuper, ObjCTypes.SuperPtrCTy,
true, CallArgs);
/// Generate code for a message send expression.
CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
QualType ResultType,
Selector Sel,
bool IsClassMessage,
const CallArgList &CallArgs) {
llvm::Value *Arg0 =
CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp");
return EmitMessageSend(CGF, ResultType, Sel,
Arg0, CGF.getContext().getObjCIdType(),
false, CallArgs);
}
CodeGen::RValue CGObjCMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
QualType ResultType,
Selector Sel,
QualType Arg0Ty,
bool IsSuper,
const CallArgList &CallArgs) {
CallArgList ActualArgs;
ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
ActualArgs.push_back(std::make_pair(RValue::get(EmitSelector(CGF.Builder,
Sel)),
CGF.getContext().getObjCSelType()));
ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
CodeGenTypes &Types = CGM.getTypes();
const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs);
const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo, false);
llvm::Constant *Fn;
Fn = ObjCTypes.getSendStretFn(IsSuper);
} else if (ResultType->isFloatingType()) {
// FIXME: Sadly, this is wrong. This actually depends on the
// architecture. This happens to be right for x86-32 though.
Fn = ObjCTypes.getSendFpretFn(IsSuper);
} else {
Fn = ObjCTypes.getSendFn(IsSuper);
}
Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
const ObjCProtocolDecl *PD) {
// FIXME: I don't understand why gcc generates this, or where it is
// resolved. Investigate. Its also wasteful to look this up over and
// over.
LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
ObjCTypes.ExternalProtocolPtrTy);
}
void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
// FIXME: We shouldn't need this, the protocol decl should contain
// enough information to tell us whether this was a declaration or a
// definition.
DefinedProtocols.insert(PD->getIdentifier());
// If we have generated a forward reference to this protocol, emit
// it now. Otherwise do nothing, the protocol objects are lazily
// emitted.
if (Protocols.count(PD->getIdentifier()))
GetOrEmitProtocol(PD);
}
llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
if (DefinedProtocols.count(PD->getIdentifier()))
return GetOrEmitProtocol(PD);
return GetOrEmitProtocolRef(PD);
}
/*
// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
struct _objc_protocol {
struct _objc_protocol_extension *isa;
char *protocol_name;
struct _objc_protocol_list *protocol_list;
struct _objc__method_prototype_list *instance_methods;
struct _objc__method_prototype_list *class_methods
};
See EmitProtocolExtension().
*/
llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
// Early exit if a defining object has already been generated.
if (Entry && Entry->hasInitializer())
return Entry;
// FIXME: I don't understand why gcc generates this, or where it is
// resolved. Investigate. Its also wasteful to look this up over and
// over.
LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
const char *ProtocolName = PD->getNameAsCString();
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
// Construct method lists.
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
for (ObjCProtocolDecl::instmeth_iterator i = PD->instmeth_begin(),
e = PD->instmeth_end(); i != e; ++i) {
ObjCMethodDecl *MD = *i;
llvm::Constant *C = GetMethodDescriptionConstant(MD);
if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
OptInstanceMethods.push_back(C);
} else {
InstanceMethods.push_back(C);
}
}
for (ObjCProtocolDecl::classmeth_iterator i = PD->classmeth_begin(),
e = PD->classmeth_end(); i != e; ++i) {
ObjCMethodDecl *MD = *i;
llvm::Constant *C = GetMethodDescriptionConstant(MD);
if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
OptClassMethods.push_back(C);
} else {
ClassMethods.push_back(C);
}
}
std::vector<llvm::Constant*> Values(5);
Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
Values[1] = GetClassName(PD->getIdentifier());
EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getNameAsString(),
PD->protocol_begin(),
PD->protocol_end());
EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_"
+ PD->getNameAsString(),
"__OBJC,__cat_inst_meth,regular,no_dead_strip",
InstanceMethods);
Values[4] =
EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_"
+ PD->getNameAsString(),
"__OBJC,__cat_cls_meth,regular,no_dead_strip",
ClassMethods);
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Values);