]> granicus.if.org Git - clang/commitdiff
Add GetAddrOfConstantCString method
authorDaniel Dunbar <daniel@zuster.org>
Wed, 13 Aug 2008 23:20:05 +0000 (23:20 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Wed, 13 Aug 2008 23:20:05 +0000 (23:20 +0000)
 - Returns addr of constant for argument + '\0'.
 - I couldn't think of a better name.
 - Move appropriate users of GetAddrOfConstantString to this.

Rename getStringForStringLiteral to GetStringForStringLiteral.

Add GetAddrOfConstantStringFromLiteral
 - This combines GetAddrOfConstantString and
   GetStringForStringLiteral. This method can be, but is not yet, more
   efficient.

Change GetAddrOfConstantString to not add terminating '\0'
 - <rdar://problem/6140956>

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54768 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExpr.cpp
lib/CodeGen/CGExprConstant.cpp
lib/CodeGen/CGObjC.cpp
lib/CodeGen/CGObjCGNU.cpp
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
test/CodeGen/c-strings.c [new file with mode: 0644]

index 6bfd5cb30999568eabf813f5a6f92d9f8eaec87b..e6bc5016e9abde6a73edfc160e72d2cf01b57703 100644 (file)
@@ -488,10 +488,7 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
 }
 
 LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) {
-  llvm::Constant *C = 
-    CGM.GetAddrOfConstantString(CGM.getStringForStringLiteral(E));
-
-  return LValue::MakeAddr(C,0);
+  return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromLiteral(E), 0);
 }
 
 LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
index 12620e71014d4edf97a9a3ef3cfa06634ca2aaec..dfd047c89dc30b0ce7684b0534d28a1c86546515 100644 (file)
@@ -363,7 +363,7 @@ public:
     // Otherwise this must be a string initializing an array in a static
     // initializer.  Don't emit it as the address of the string, emit the string
     // data itself as an inline array.
-    return llvm::ConstantArray::get(CGM.getStringForStringLiteral(E), false);
+    return llvm::ConstantArray::get(CGM.GetStringForStringLiteral(E), false);
   }
 
   llvm::Constant *VisitDeclRefExpr(DeclRefExpr *E) {
@@ -762,10 +762,8 @@ public:
              "Taking the address of a vector component is illegal!");
       return llvm::ConstantExpr::getGetElementPtr(Base, &Index, 1);
     }
-    case Expr::StringLiteralClass: {
-      StringLiteral *S = cast<StringLiteral>(E);
-      return CGM.GetAddrOfConstantString(CGM.getStringForStringLiteral(S));
-    }
+    case Expr::StringLiteralClass:
+      return CGM.GetAddrOfConstantStringFromLiteral(cast<StringLiteral>(E));
     case Expr::UnaryOperatorClass: {
       UnaryOperator *Exp = cast<UnaryOperator>(E);
       switch (Exp->getOpcode()) {
index 7270884572263687a8702231663f3a2f381d371b..2e400f4d2aee498cb3db31b33e6cf263fcc61458 100644 (file)
@@ -52,7 +52,7 @@ llvm::Value *CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) {
     if (!strcmp(classname, "super")) {
       classname = E->getMethodDecl()->getClassInterface()->getName();
     }
-    llvm::Value *ClassName = CGM.GetAddrOfConstantString(classname);
+    llvm::Value *ClassName = CGM.GetAddrOfConstantCString(classname);
     ClassName = Builder.CreateStructGEP(ClassName, 0);
     Receiver = Runtime.LookupClass(Builder, ClassName);
   } else if (const PredefinedExpr *PDE =
index 61552c45052e4b1a3f3162736f72eb60514ec29f..c4d236b54d4c0f60b71a3e460057df1e21c7f150 100644 (file)
@@ -370,7 +370,7 @@ llvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName,
   std::vector<llvm::Constant*> Elements;
   for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) {
     Elements.clear();
-    llvm::Constant *C = CGM.GetAddrOfConstantString(MethodSels[i].getName());
+    llvm::Constant *C = CGM.GetAddrOfConstantCString(MethodSels[i].getName());
     Elements.push_back(llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2));
     Elements.push_back(
           llvm::ConstantExpr::getGetElementPtr(MethodTypes[i], Zeros, 2));
@@ -581,8 +581,8 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
     std::string TypeStr;
     Context.getObjCEncodingForMethodDecl(*iter, TypeStr);
     InstanceMethodNames.push_back(
-        CGM.GetAddrOfConstantString((*iter)->getSelector().getName()));
-    InstanceMethodTypes.push_back(CGM.GetAddrOfConstantString(TypeStr));
+        CGM.GetAddrOfConstantCString((*iter)->getSelector().getName()));
+    InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
   }
   // Collect information about class methods:
   llvm::SmallVector<llvm::Constant*, 16> ClassMethodNames;
@@ -592,8 +592,8 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
     std::string TypeStr;
     Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
     ClassMethodNames.push_back(
-        CGM.GetAddrOfConstantString((*iter)->getSelector().getName()));
-    ClassMethodTypes.push_back(CGM.GetAddrOfConstantString(TypeStr));
+        CGM.GetAddrOfConstantCString((*iter)->getSelector().getName()));
+    ClassMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr));
   }
 
   llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
index f575300b6dd5b19c8a2ce1f4c02c3e331f0dce84..c6b02f83b412abb5796b25c23044b47e2ca08bfe 100644 (file)
@@ -261,7 +261,7 @@ void CodeGenModule::EmitObjCCategoryImpl(const ObjCCategoryImplDecl *OCD) {
     InstanceMethodSels.push_back((*iter)->getSelector());
     std::string TypeStr;
     Context.getObjCEncodingForMethodDecl(*iter,TypeStr);
-    InstanceMethodTypes.push_back(GetAddrOfConstantString(TypeStr));
+    InstanceMethodTypes.push_back(GetAddrOfConstantCString(TypeStr));
   }
 
   // Collect information about class methods
@@ -272,7 +272,7 @@ void CodeGenModule::EmitObjCCategoryImpl(const ObjCCategoryImplDecl *OCD) {
     ClassMethodSels.push_back((*iter)->getSelector());
     std::string TypeStr;
     Context.getObjCEncodingForMethodDecl(*iter,TypeStr);
-    ClassMethodTypes.push_back(GetAddrOfConstantString(TypeStr));
+    ClassMethodTypes.push_back(GetAddrOfConstantCString(TypeStr));
   }
 
   // Collect the names of referenced protocols
@@ -325,13 +325,13 @@ void CodeGenModule::EmitObjCClassImplementation(
   for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(),
       endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) {
       // Store the name
-      IvarNames.push_back(GetAddrOfConstantString((*iter)->getName()));
+      IvarNames.push_back(GetAddrOfConstantCString((*iter)->getName()));
       // Get the type encoding for this ivar
       std::string TypeStr;
       llvm::SmallVector<const RecordType *, 8> EncodingRecordTypes;
       Context.getObjCEncodingForType((*iter)->getType(), TypeStr,
                                      EncodingRecordTypes);
-      IvarTypes.push_back(GetAddrOfConstantString(TypeStr));
+      IvarTypes.push_back(GetAddrOfConstantCString(TypeStr));
       // Get the offset
       int offset =
         (int)Layout->getElementOffset(getTypes().getLLVMFieldNo(*iter));
@@ -347,7 +347,7 @@ void CodeGenModule::EmitObjCClassImplementation(
     InstanceMethodSels.push_back((*iter)->getSelector());
     std::string TypeStr;
     Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
-    InstanceMethodTypes.push_back(GetAddrOfConstantString(TypeStr));
+    InstanceMethodTypes.push_back(GetAddrOfConstantCString(TypeStr));
   }
 
   // Collect information about class methods
@@ -358,7 +358,7 @@ void CodeGenModule::EmitObjCClassImplementation(
     ClassMethodSels.push_back((*iter)->getSelector());
     std::string TypeStr;
     Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
-    ClassMethodTypes.push_back(GetAddrOfConstantString(TypeStr));
+    ClassMethodTypes.push_back(GetAddrOfConstantCString(TypeStr));
   }
   // Collect the names of referenced protocols
   llvm::SmallVector<std::string, 16> Protocols;
@@ -888,9 +888,9 @@ GetAddrOfConstantCFString(const std::string &str) {
   return GV;
 }
 
-/// getStringForStringLiteral - Return the appropriate bytes for a
+/// GetStringForStringLiteral - Return the appropriate bytes for a
 /// string literal, properly padded to match the literal type.
-std::string CodeGenModule::getStringForStringLiteral(const StringLiteral *E) {
+std::string CodeGenModule::GetStringForStringLiteral(const StringLiteral *E) {
   assert(!E->isWide() && "FIXME: Wide strings not supported yet!");
   const char *StrData = E->getStrData();
   unsigned Len = E->getByteLength();
@@ -908,22 +908,37 @@ std::string CodeGenModule::getStringForStringLiteral(const StringLiteral *E) {
   return Str;
 }
 
+/// GetAddrOfConstantStringFromLiteral - Return a pointer to a
+/// constant array for the given string literal.
+llvm::Constant *
+CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) {
+  // FIXME: This can be more efficient.
+  return GetAddrOfConstantString(GetStringForStringLiteral(S));
+}
+
 /// GenerateWritableString -- Creates storage for a string literal.
 static llvm::Constant *GenerateStringLiteral(const std::string &str, 
                                              bool constant,
                                              CodeGenModule &CGM) {
-  // Create Constant for this string literal
-  llvm::Constant *C = llvm::ConstantArray::get(str);
+  // Create Constant for this string literal. Don't add a '\0'.
+  llvm::Constant *C = llvm::ConstantArray::get(str, false);
   
   // Create a global variable for this string
   C = new llvm::GlobalVariable(C->getType(), constant, 
                                llvm::GlobalValue::InternalLinkage,
                                C, ".str", &CGM.getModule());
+
   return C;
 }
 
-/// CodeGenModule::GetAddrOfConstantString -- returns a pointer to the character
-/// array containing the literal.  The result is pointer to array type.
+/// GetAddrOfConstantString - Returns a pointer to a character array
+/// containing the literal. This contents are exactly that of the
+/// given string, i.e. it will not be null terminated automatically;
+/// see GetAddrOfConstantCString. Note that whether the result is
+/// actually a pointer to an LLVM constant depends on
+/// Feature.WriteableStrings.
+///
+/// The result has pointer to array type.
 llvm::Constant *CodeGenModule::GetAddrOfConstantString(const std::string &str) {
   // Don't share any string literals if writable-strings is turned on.
   if (Features.WritableStrings)
@@ -940,3 +955,10 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantString(const std::string &str) {
   Entry.setValue(C);
   return C;
 }
+
+/// GetAddrOfConstantCString - Returns a pointer to a character
+/// array containing the literal and a terminating '\-'
+/// character. The result has pointer to array type.
+llvm::Constant *CodeGenModule::GetAddrOfConstantCString(const std::string &str) {
+  return GetAddrOfConstantCString(str + "\0");
+}
index a837b6369c320d8a42febb270d08318526243df0..dd8ac1739f920a0aa59fedae309338525e48219d 100644 (file)
@@ -143,15 +143,34 @@ public:
   /// "__builtin_fabsf", return a Function* for "fabsf".
   ///
   llvm::Function *getBuiltinLibFunction(unsigned BuiltinID);
+
+  /// GetStringForStringLiteral - Return the appropriate bytes for a
+  /// string literal, properly padded to match the literal type. If
+  /// only the address of a constant is needed consider using
+  /// GetAddrOfConstantStringLiteral.
+  std::string GetStringForStringLiteral(const StringLiteral *E);
+
   llvm::Constant *GetAddrOfConstantCFString(const std::string& str);
 
-  /// getStringForStringLiteral - Return the appropriate bytes for a
-  /// string literal, properly padded to match the literal type.
-  std::string getStringForStringLiteral(const StringLiteral *E);
+  /// GetAddrOfConstantStringFromLiteral - Return a pointer to a
+  /// constant array for the given string literal.
+  llvm::Constant *GetAddrOfConstantStringFromLiteral(const StringLiteral *S);
 
-  /// GetAddrOfConstantString -- returns a pointer to the character
-  /// array containing the literal.  The result is pointer to array type.
+  /// GetAddrOfConstantString - Returns a pointer to a character array
+  /// containing the literal. This contents are exactly that of the
+  /// given string, i.e. it will not be null terminated automatically;
+  /// see GetAddrOfConstantCString. Note that whether the result is
+  /// actually a pointer to an LLVM constant depends on
+  /// Feature.WriteableStrings.
+  ///
+  /// The result has pointer to array type.
   llvm::Constant *GetAddrOfConstantString(const std::string& str);
+
+  /// GetAddrOfConstantCString - Returns a pointer to a character
+  /// array containing the literal and a terminating '\-'
+  /// character. The result has pointer to array type.
+  llvm::Constant *GetAddrOfConstantCString(const std::string &str);
+
   llvm::Function *getMemCpyFn();
   llvm::Function *getMemMoveFn();
   llvm::Function *getMemSetFn();
diff --git a/test/CodeGen/c-strings.c b/test/CodeGen/c-strings.c
new file mode 100644 (file)
index 0000000..baff4dd
--- /dev/null
@@ -0,0 +1,34 @@
+// RUN: clang -emit-llvm -o %t %s &&
+// RUN: grep "hello" %t | count 3 &&
+// RUN: grep 'c"hello\\00"' %t | count 2 &&
+// RUN: grep 'c"hello\\00\\00\\00"' %t | count 1
+
+/* Should be 3 hello string, two global (of different sizes), the rest
+   are shared. */
+
+void f0() {
+  bar("hello");
+}
+
+void f1() {
+  static char *x = "hello";
+  bar(x);
+}
+
+void f2() {
+  static char x[] = "hello";
+  bar(x);
+}
+
+void f3() {
+  static char x[8] = "hello";
+  bar(x);
+}
+
+void f4() {
+  static struct s {
+    char *name;
+  } x = { "hello" };
+  gaz(&x);
+}
+