[cfe-commits] r55209 - /cfe/trunk/lib/CodeGen/CGObjCMac.cpp

Daniel Dunbar daniel at zuster.org
Fri Aug 22 17:19:03 PDT 2008


Author: ddunbar
Date: Fri Aug 22 19:19:03 2008
New Revision: 55209

URL: http://llvm.org/viewvc/llvm-project?rev=55209&view=rev
Log:
NeXT: Emit property metadata (classes, protocols, categories).

Modified:
    cfe/trunk/lib/CodeGen/CGObjCMac.cpp

Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=55209&r1=55208&r2=55209&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Fri Aug 22 19:19:03 2008
@@ -80,8 +80,12 @@
   /// 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 @@
   /// 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 @@
   /// 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 @@
                                      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 @@
   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 @@
                                  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() && 
@@ -623,6 +644,57 @@
 }
 
 /*
+  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;
     struct objc_method_description list[];
@@ -705,19 +777,25 @@
   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,
-                             "__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,
-                             "__OBJC,__cat_class_meth,regular,no_dead_strip",
-                             OCD->classmeth_begin(),
-                             OCD->classmeth_end());
-  Values[4] = EmitProtocolList(std::string("\01L_OBJC_CATEGORY_PROTOCOLS_") + ExtName,
-                               Interface->protocol_begin(),
-                               Interface->protocol_end());
+  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,
+                   "__OBJC,__cat_class_meth,regular,no_dead_strip",
+                   OCD->classmeth_begin(),
+                   OCD->classmeth_end());
+  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,10 +893,11 @@
   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(),
-                              "__OBJC,__inst_meth,regular,no_dead_strip",
-                              ID->instmeth_begin(),
-                              ID->instmeth_end());
+  Values[ 7] = 
+    EmitMethodList(std::string("\01L_OBJC_INSTANCE_METHODS_") + ID->getName(),
+                   "__OBJC,__inst_meth,regular,no_dead_strip",
+                   ID->instmeth_begin(),
+                   ID->instmeth_end());
   // cache is always NULL.
   Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
   Values[ 9] = Protocols;
@@ -875,10 +954,11 @@
   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(),
-                              "__OBJC,__inst_meth,regular,no_dead_strip",
-                              ID->classmeth_begin(),
-                              ID->classmeth_end());
+  Values[ 7] = 
+    EmitMethodList(std::string("\01L_OBJC_CLASS_METHODS_") + ID->getName(),
+                   "__OBJC,__inst_meth,regular,no_dead_strip",
+                   ID->classmeth_begin(),
+                   ID->classmeth_end());
   // cache is always NULL.
   Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
   Values[ 9] = Protocols;
@@ -919,10 +999,10 @@
   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 @@
   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 @@
   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);





More information about the cfe-commits mailing list