[cfe-commits] r54659 - in /cfe/trunk/lib/CodeGen: CGExprConstant.cpp CGObjC.cpp CGObjCGNU.cpp CGObjCMac.cpp CGObjCRuntime.h

Daniel Dunbar daniel at zuster.org
Mon Aug 11 17:12:39 PDT 2008


Author: ddunbar
Date: Mon Aug 11 19:12:39 2008
New Revision: 54659

URL: http://llvm.org/viewvc/llvm-project?rev=54659&view=rev
Log:
Add ObjC constant string support for NeXT.

Changed CGObjCRuntime::GenerateConstantString interface to take
       std::string instead of char* and size.

Change ObjC functions which call on GenerateConstantString to bitcast
       result to appropriate type.

Modified:
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
    cfe/trunk/lib/CodeGen/CGObjCMac.cpp
    cfe/trunk/lib/CodeGen/CGObjCRuntime.h

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Mon Aug 11 19:12:39 2008
@@ -61,8 +61,10 @@
     return llvm::ConstantInt::get(ConvertType(E->getType()), E->getValue());
   }
   llvm::Constant *VisitObjCStringLiteral(const ObjCStringLiteral *E) {
-    return CGM.getObjCRuntime().GenerateConstantString(
-        E->getString()->getStrData(), E->getString()->getByteLength());
+    std::string S(E->getString()->getStrData(), 
+                  E->getString()->getByteLength());
+    llvm::Constant *C = CGM.getObjCRuntime().GenerateConstantString(S);
+    return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
   }
   
   llvm::Constant *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Mon Aug 11 19:12:39 2008
@@ -20,9 +20,10 @@
 using namespace CodeGen;
 
 /// Emits an instance of NSConstantString representing the object.
-llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E){
-  return CGM.getObjCRuntime().GenerateConstantString(
-      E->getString()->getStrData(), E->getString()->getByteLength());
+llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E) {
+  std::string String(E->getString()->getStrData(), E->getString()->getByteLength());
+  llvm::Constant *C = CGM.getObjCRuntime().GenerateConstantString(String);
+  return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
 }
 
 /// Emit a selector.

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Mon Aug 11 19:12:39 2008
@@ -90,8 +90,7 @@
       std::vector<llvm::Constant*> &V, const std::string &Name="");
 public:
   CGObjCGNU(CodeGen::CodeGenModule &cgm);
-  virtual llvm::Constant *GenerateConstantString(const char *String, 
-      const size_t length);
+  virtual llvm::Constant *GenerateConstantString(const std::string &String);
   virtual llvm::Value *GenerateMessageSend(llvm::IRBuilder<> &Builder,
                                            const llvm::Type *ReturnTy,
                                            llvm::Value *Sender,
@@ -248,13 +247,11 @@
 //TODO: In case there are any crazy people still using the GNU runtime without
 //an OpenStep implementation, this should let them select their own class for
 //constant strings.
-llvm::Constant *CGObjCGNU::GenerateConstantString(const char *String, const
-    size_t length) {
-  std::string Str(String, String +length);
+llvm::Constant *CGObjCGNU::GenerateConstantString(const std::string &Str) {
   std::vector<llvm::Constant*> Ivars;
   Ivars.push_back(NULLPtr);
   Ivars.push_back(MakeConstantString(Str));
-  Ivars.push_back(llvm::ConstantInt::get(IntTy, length));
+  Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size()));
   llvm::Constant *ObjCStr = MakeGlobal(
     llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL),
     Ivars, ".objc_str");

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Mon Aug 11 19:12:39 2008
@@ -14,17 +14,43 @@
 #include "CGObjCRuntime.h"
 
 #include "CodeGenModule.h"
+#include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/Basic/LangOptions.h"
 
+#include "llvm/Module.h"
 #include "llvm/Support/IRBuilder.h"
 
 using namespace clang;
 
 namespace {
+
+/// ObjCTypesHelper - Helper class that encapsulates lazy
+/// construction of varies types used during ObjC generation.
+class ObjCTypesHelper {
+private:
+  CodeGen::CodeGenModule &CGM;  
+  
+  const llvm::StructType *CFStringType;
+  llvm::Constant *CFConstantStringClassReference;
+  
+public:
+  const llvm::Type *LongTy;
+  
+public:
+  ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
+  ~ObjCTypesHelper();
+  
+  llvm::Constant *getCFConstantStringClassReference();
+  const llvm::StructType *getCFStringType();
+};
+
 class CGObjCMac : public CodeGen::CGObjCRuntime {
 private:
-  CodeGen::CodeGenModule &CGM;
+  CodeGen::CodeGenModule &CGM;  
+  ObjCTypesHelper ObjCTypes;
+  /// ObjCABI - FIXME: Not sure yet.
+  unsigned ObjCABI;
 
   /// UsedGlobals - list of globals to pack into the llvm.used metadata
   /// to prevent them from being clobbered.
@@ -40,8 +66,7 @@
 
 public:
   CGObjCMac(CodeGen::CodeGenModule &cgm);
-  virtual llvm::Constant *GenerateConstantString(const char *String, 
-                                                 const size_t length);
+  virtual llvm::Constant *GenerateConstantString(const std::string &String);
 
   virtual llvm::Value *GenerateMessageSend(llvm::IRBuilder<> &Builder,
                                            const llvm::Type *ReturnTy,
@@ -108,9 +133,32 @@
   virtual llvm::Function *ModuleInitFunction();
 };
 } // 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) : CGM(cgm) {
-  EmitImageInfo();
+CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) 
+  : CGM(cgm),
+    ObjCTypes(cgm),
+    ObjCABI(1)
+{
+  // FIXME: How does this get set in GCC? And what does it even mean?
+  if (ObjCTypes.LongTy != CGM.getTypes().ConvertType(CGM.getContext().IntTy))
+      ObjCABI = 2;
+
+  EmitImageInfo();  
 }
 
 // This has to perform the lookup every time, since posing and related
@@ -127,11 +175,51 @@
   return 0;
 }
 
-/// Generate an NSConstantString object.
-llvm::Constant *CGObjCMac::GenerateConstantString(const char *String, 
-                                                  const size_t length) {
-  assert(0 && "Cannot generate constant string for Mac runtime.");
-  return 0;
+/// Generate a constant CFString object.
+/* 
+   struct __builtin_CFString {
+     const int *isa; // point to __CFConstantStringClassReference
+     int flags;
+     const char *str;
+     long length;
+   };
+*/
+
+llvm::Constant *CGObjCMac::GenerateConstantString(const std::string &String) {
+  // FIXME: I have no idea what this constant is (it is a magic
+  // constant in GCC as well). Most likely the encoding of the string
+  // and at least one part of it relates to UTF-16. Is this just the
+  // code for UTF-8? Where is this handled for us?
+  //  See: <rdr://2996215>
+  unsigned flags = 0x07c8;
+
+  // FIXME: Use some machinery to unique this. We can't reuse the CGM
+  // one since we put them in a different section.
+  llvm::Constant *StringC = llvm::ConstantArray::get(String);
+  llvm::Constant *StringGV = 
+    new llvm::GlobalVariable(StringC->getType(), true, 
+                             llvm::GlobalValue::InternalLinkage,
+                             StringC, ".str", &CGM.getModule());
+  llvm::Constant *Values[4] = {
+    ObjCTypes.getCFConstantStringClassReference(),
+    llvm::ConstantInt::get(llvm::Type::Int32Ty, flags),
+    getConstantGEP(StringGV, 0, 0), // Decay array -> ptr
+    llvm::ConstantInt::get(ObjCTypes.LongTy, String.size())
+  };
+
+  llvm::Constant *CFStringC = 
+    llvm::ConstantStruct::get(ObjCTypes.getCFStringType(), 
+                              std::vector<llvm::Constant*>(Values, Values+4));
+
+  llvm::GlobalVariable *CFStringGV = 
+    new llvm::GlobalVariable(CFStringC->getType(), true,
+                             llvm::GlobalValue::InternalLinkage,
+                             CFStringC, "",
+                             &CGM.getModule());
+
+  CFStringGV->setSection("__DATA, __cfstring");
+
+  return CFStringGV;
 }
 
 /// Generates a message send where the super is the receiver.  This is
@@ -249,8 +337,6 @@
   if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
     flags |= eImageInfo_GCOnly;
 
-  fprintf(stderr, "flags: %d (%d)\n", flags, CGM.getLangOptions().getGCMode());
-
   // Emitted as int[2];
   llvm::Constant *values[2] = {
     llvm::ConstantInt::get(llvm::Type::Int32Ty, version),
@@ -264,7 +350,11 @@
                              "\01L_OBJC_IMAGE_INFO", 
                              &CGM.getModule());
 
-  GV->setSection("__OBJC, __image_info,regular");
+  if (ObjCABI == 1) {
+    GV->setSection("__OBJC, __image_info,regular");
+  } else {
+    GV->setSection("__DATA, __objc_imageinfo, regular, no_dead_strip");
+  }
 
   UsedGlobals.push_back(GV);
 }
@@ -291,6 +381,50 @@
 
 /* *** */
 
+ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) 
+  : CGM(cgm),
+    CFStringType(0),
+    CFConstantStringClassReference(0),
+    LongTy(CGM.getTypes().ConvertType(CGM.getContext().LongTy))
+{
+}
+
+ObjCTypesHelper::~ObjCTypesHelper() {
+}
+
+const llvm::StructType *ObjCTypesHelper::getCFStringType() {
+  if (!CFStringType) {
+    CFStringType = 
+      llvm::StructType::get(llvm::PointerType::getUnqual(llvm::Type::Int32Ty), 
+                            llvm::Type::Int32Ty,
+                            llvm::PointerType::getUnqual(llvm::Type::Int8Ty),
+                            LongTy,
+                            NULL);
+
+    CGM.getModule().addTypeName("struct.__builtin_CFString", CFStringType);
+  }
+
+  return CFStringType;
+}
+
+llvm::Constant *ObjCTypesHelper::getCFConstantStringClassReference() {
+  if (!CFConstantStringClassReference) {
+    llvm::GlobalValue *GV = 
+      new llvm::GlobalVariable(llvm::ArrayType::get(llvm::Type::Int32Ty, 0), 
+                               false,
+                               llvm::GlobalValue::ExternalLinkage,
+                               0, "__CFConstantStringClassReference", 
+                                                     &CGM.getModule());
+
+    // Decay to pointer.
+    CFConstantStringClassReference = getConstantGEP(GV, 0, 0);
+  }
+
+  return CFConstantStringClassReference;
+}
+
+/* *** */
+
 CodeGen::CGObjCRuntime *CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM){
   return new CGObjCMac(CGM);
 }

Modified: cfe/trunk/lib/CodeGen/CGObjCRuntime.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCRuntime.h?rev=54659&r1=54658&r2=54659&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCRuntime.h (original)
+++ cfe/trunk/lib/CodeGen/CGObjCRuntime.h Mon Aug 11 19:12:39 2008
@@ -59,8 +59,7 @@
   virtual llvm::Value *GetSelector(BuilderType &Builder,
                                    Selector Sel) =0;
   /// Generate a constant string object
-  virtual llvm::Constant *GenerateConstantString(const char *String,
-                                                 const size_t Length) = 0;
+  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,





More information about the cfe-commits mailing list