Implement code generation for constant CFStrings.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41206 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/CodeGen/CodeGenModule.cpp b/CodeGen/CodeGenModule.cpp
index 44cb91d..74c7d43 100644
--- a/CodeGen/CodeGenModule.cpp
+++ b/CodeGen/CodeGenModule.cpp
@@ -26,7 +26,7 @@
 
 
 CodeGenModule::CodeGenModule(ASTContext &C, llvm::Module &M)
-  : Context(C), TheModule(M), Types(C, M) {}
+  : Context(C), TheModule(M), Types(C, M), CFConstantStringClassRef(0) {}
 
 llvm::Constant *CodeGenModule::GetAddrOfGlobalDecl(const Decl *D) {
   // See if it is already in the map.
@@ -113,3 +113,59 @@
   }
   return MemCpyFn = llvm::Intrinsic::getDeclaration(&TheModule, IID);
 }
+
+llvm::Constant *CodeGenModule::GetAddrOfConstantCFString(const std::string &str)
+{
+  llvm::StringMapEntry<llvm::Constant *> &Entry = 
+    CFConstantStringMap.GetOrCreateValue(&str[0], &str[str.length()]);
+  
+  if (Entry.getValue())
+    return Entry.getValue();
+  
+  std::vector<llvm::Constant*> Fields;
+  
+  if (!CFConstantStringClassRef) {
+    const llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy);
+    Ty = llvm::ArrayType::get(Ty, 0);
+  
+    CFConstantStringClassRef = 
+      new llvm::GlobalVariable(Ty, false,
+                               llvm::GlobalVariable::ExternalLinkage, 0, 
+                               "__CFConstantStringClassReference", 
+                               &getModule());
+  }
+  
+  // Class pointer.
+  llvm::Constant *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty);
+  llvm::Constant *Zeros[] = { Zero, Zero };
+  llvm::Constant *C = 
+    llvm::ConstantExpr::getGetElementPtr(CFConstantStringClassRef, Zeros, 2);
+  Fields.push_back(C);
+  
+  // Flags.
+  const llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy);
+  Fields.push_back(llvm::ConstantInt::get(Ty, 1992));
+    
+  // String pointer.
+  C = llvm::ConstantArray::get(str);
+  C = new llvm::GlobalVariable(C->getType(), true, 
+                               llvm::GlobalValue::InternalLinkage,
+                               C, ".str", &getModule());
+  
+  C = llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2);
+  Fields.push_back(C);
+  
+  // String length.
+  Ty = getTypes().ConvertType(getContext().LongTy);
+  Fields.push_back(llvm::ConstantInt::get(Ty, str.length()));
+  
+  // The struct.
+  Ty = getTypes().ConvertType(getContext().getCFConstantStringType());
+  C = llvm::ConstantStruct::get(cast<llvm::StructType>(Ty), Fields);
+  C = new llvm::GlobalVariable(C->getType(), true, 
+                               llvm::GlobalVariable::InternalLinkage, 
+                               C, "", &getModule());
+  
+  Entry.setValue(C);
+  return C;
+}