NeXT: Emit property metadata (classes, protocols, categories).

llvm-svn: 55209
This commit is contained in:
Daniel Dunbar 2008-08-23 00:19:03 +00:00
parent bb170bd08c
commit 80a840bc70
1 changed files with 150 additions and 36 deletions

View File

@ -80,8 +80,12 @@ public:
/// MethodDescriptionListPtrTy - LLVM type for struct
/// objc_method_description_list *.
const llvm::Type *MethodDescriptionListPtrTy;
/// PropertyListTy - LLVM type for struct objc_property_list.
const llvm::Type *PropertyListTy;
/// 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;
/// ProtocolListTy - LLVM type for struct objc_property_list.
@ -141,6 +145,9 @@ private:
/// a StringMap here because have no other unique reference.
llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
/// PropertyNames - uniqued method variable names.
llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
/// ClassReferences - uniqued class references.
llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
@ -206,7 +213,7 @@ private:
/// EmitMethodList - Emit the method list for the given
/// implementation. If ForClass is true the list of class methods
/// will be emitted, otherwise the list of instance methods will be
/// generated.The return value has type MethodListPtrTy.
/// generated. The return value has type MethodListPtrTy.
llvm::Constant *EmitMethodList(const std::string &Name,
const char *Section,
llvm::SmallVector<ObjCMethodDecl*, 32>::const_iterator begin,
@ -230,6 +237,12 @@ private:
ObjCMethodDecl * const *begin,
ObjCMethodDecl * const *end);
/// EmitPropertyList - Emit the given property list. The return
/// value has type PropertyListPtrTy.
llvm::Constant *EmitPropertyList(const std::string &Name,
ObjCPropertyDecl * const *begin,
ObjCPropertyDecl * const *end);
/// EmitProtocolExtension - Generate the protocol extension
/// structure used to store optional instance and class methods, and
/// protocol properties. The return value has type
@ -256,18 +269,25 @@ private:
llvm::Constant *GetClassName(IdentifierInfo *Ident);
/// GetMethodVarName - Return a unique constant for the given
/// selector's name. This returns a constant i8* to the start of
/// the name. The return value has type char *.
/// selector's name. The return value has type char *.
llvm::Constant *GetMethodVarName(Selector Sel);
llvm::Constant *GetMethodVarName(IdentifierInfo *);
llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
llvm::Constant *GetMethodVarName(const std::string &Name);
/// GetMethodVarType - Return a unique constant for the given
/// selector's name. This returns a constant i8* to the start of
/// the name. The return value has type char *.
/// selector's name. The return value has type char *.
// FIXME: This is a horrible name.
llvm::Constant *GetMethodVarType(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 is a horrible name too.
llvm::Constant *GetPropertyType(const ObjCPropertyDecl *PD);
/// GetNameForMethod - Return a name for the given method.
/// \param[out] NameOut - The return value.
void GetNameForMethod(const ObjCMethodDecl *OMD,
@ -555,9 +575,10 @@ llvm::Constant *CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD) {
false, // Required
PD->classmeth_begin(),
PD->classmeth_end());
Values[3] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
assert(!PD->getNumPropertyDecl() &&
"Cannot emit Obj-C protocol properties for NeXT runtime.");
Values[3] = EmitPropertyList(std::string("\01L_OBJC_$_PROP_PROTO_LIST_") +
PD->getName(),
PD->classprop_begin(),
PD->classprop_end());
// Return null if no extension bits are used.
if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
@ -622,6 +643,57 @@ CGObjCMac::EmitProtocolList(const std::string &Name,
return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
}
/*
struct _objc_property {
const char * const name;
const char * const attributes;
};
struct _objc_property_list {
uint32_t entsize; // sizeof (struct _objc_property)
uint32_t prop_count;
struct _objc_property[prop_count];
};
*/
llvm::Constant *CGObjCMac::EmitPropertyList(const std::string &Name,
ObjCPropertyDecl * const *begin,
ObjCPropertyDecl * const *end) {
std::vector<llvm::Constant*> Properties, Prop(2);
for (; begin != end; ++begin) {
const ObjCPropertyDecl *PD = *begin;
Prop[0] = GetPropertyName(PD->getIdentifier());
Prop[1] = GetPropertyType(PD);
Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Prop));
}
// Return null for empty list.
if (Properties.empty())
return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
unsigned PropertySize =
CGM.getTargetData().getABITypeSize(ObjCTypes.PropertyTy);
std::vector<llvm::Constant*> Values(3);
Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Properties.size());
Values[2] = llvm::ConstantArray::get(AT, Properties);
llvm::Constant *Init = llvm::ConstantStruct::get(Values);
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(Init->getType(), false,
llvm::GlobalValue::InternalLinkage,
Init,
Name,
&CGM.getModule());
// No special section on property lists?
UsedGlobals.push_back(GV);
return llvm::ConstantExpr::getBitCast(GV,
ObjCTypes.PropertyListPtrTy);
}
/*
struct objc_method_description_list {
int count;
@ -705,19 +777,25 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
std::vector<llvm::Constant*> Values(7);
Values[0] = GetClassName(OCD->getIdentifier());
Values[1] = GetClassName(Interface->getIdentifier());
Values[2] = EmitMethodList(std::string("\01L_OBJC_CATEGORY_INSTANCE_METHODS_") + ExtName,
Values[2] =
EmitMethodList(std::string("\01L_OBJC_CATEGORY_INSTANCE_METHODS_") +
ExtName,
"__OBJC,__cat_inst_meth,regular,no_dead_strip",
OCD->instmeth_begin(),
OCD->instmeth_end());
Values[3] = EmitMethodList(std::string("\01L_OBJC_CATEGORY_CLASS_METHODS_") + ExtName,
Values[3] =
EmitMethodList(std::string("\01L_OBJC_CATEGORY_CLASS_METHODS_") + ExtName,
"__OBJC,__cat_class_meth,regular,no_dead_strip",
OCD->classmeth_begin(),
OCD->classmeth_end());
Values[4] = EmitProtocolList(std::string("\01L_OBJC_CATEGORY_PROTOCOLS_") + ExtName,
Values[4] =
EmitProtocolList(std::string("\01L_OBJC_CATEGORY_PROTOCOLS_") + ExtName,
Interface->protocol_begin(),
Interface->protocol_end());
Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Values[6] = EmitPropertyList(std::string("\01L_OBJC_$_PROP_LIST_") + ExtName,
Interface->classprop_begin(),
Interface->classprop_end());
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Values);
@ -815,7 +893,8 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Values[ 6] = EmitIvarList(ID, false, InterfaceTy);
Values[ 7] = EmitMethodList(std::string("\01L_OBJC_INSTANCE_METHODS_") + ID->getName(),
Values[ 7] =
EmitMethodList(std::string("\01L_OBJC_INSTANCE_METHODS_") + ID->getName(),
"__OBJC,__inst_meth,regular,no_dead_strip",
ID->instmeth_begin(),
ID->instmeth_end());
@ -875,7 +954,8 @@ llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Values[ 6] = EmitIvarList(ID, true, InterfaceTy);
Values[ 7] = EmitMethodList(std::string("\01L_OBJC_CLASS_METHODS_") + ID->getName(),
Values[ 7] =
EmitMethodList(std::string("\01L_OBJC_CLASS_METHODS_") + ID->getName(),
"__OBJC,__inst_meth,regular,no_dead_strip",
ID->classmeth_begin(),
ID->classmeth_end());
@ -919,10 +999,10 @@ CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
// FIXME: Output weak_ivar_layout string.
Values[1] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
// FIXME: Output properties.
Values[2] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
assert(!ID->getClassInterface()->getNumPropertyDecl() &&
"Cannot emit Obj-C class properties for NeXt runtime.");
Values[2] = EmitPropertyList(std::string("\01L_OBJC_$_PROP_LIST_") +
ID->getName(),
ID->getClassInterface()->classprop_begin(),
ID->getClassInterface()->classprop_end());
// Return null if no extension bits are used.
if (Values[1]->isNullValue() && Values[2]->isNullValue())
@ -1362,6 +1442,31 @@ llvm::Constant *CGObjCMac::GetMethodVarType(ObjCMethodDecl *D) {
return GetMethodVarType(TypeStr);
}
// FIXME: Merge into a single cstring creation function.
llvm::Constant *CGObjCMac::GetPropertyName(IdentifierInfo *Ident) {
llvm::GlobalVariable *&Entry = PropertyNames[Ident];
if (!Entry) {
llvm::Constant *C = llvm::ConstantArray::get(Ident->getName());
Entry =
new llvm::GlobalVariable(C->getType(), false,
llvm::GlobalValue::InternalLinkage,
C, "\01L_OBJC_PROP_NAME_ATTR_",
&CGM.getModule());
Entry->setSection("__TEXT,__cstring,cstring_literals");
UsedGlobals.push_back(Entry);
}
return getConstantGEP(Entry, 0, 0);
}
// FIXME: Merge into a single cstring creation function.
llvm::Constant *CGObjCMac::GetPropertyType(const ObjCPropertyDecl *PD) {
std::string TypeStr("MOOO!");
//CGM.getContext().getObjCEncodingForMethodDecl(D, TypeStr);
return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
}
void CGObjCMac::GetNameForMethod(const ObjCMethodDecl *D,
std::string &NameOut) {
// FIXME: Find the mangling GCC uses.
@ -1436,7 +1541,16 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
MethodDescriptionListPtrTy =
llvm::PointerType::getUnqual(MethodDescriptionListTy);
PropertyListTy = llvm::OpaqueType::get();
PropertyTy = llvm::StructType::get(Int8PtrTy,
Int8PtrTy,
NULL);
CGM.getModule().addTypeName("struct._objc_property",
PropertyTy);
PropertyListTy = llvm::StructType::get(IntTy,
IntTy,
llvm::ArrayType::get(PropertyTy, 0),
NULL);
CGM.getModule().addTypeName("struct._objc_property_list",
PropertyListTy);
PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);