OSDN Git Service

Add support emiting for 2/4 byte mergable strings to the ".rodata.str*"
authorChris Lattner <sabre@nondot.org>
Tue, 4 Aug 2009 16:13:09 +0000 (16:13 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 4 Aug 2009 16:13:09 +0000 (16:13 +0000)
section on ELF targets.

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

lib/Target/TargetLoweringObjectFile.cpp
test/CodeGen/X86/global-sections.ll

index f2c7988..7d8f529 100644 (file)
@@ -79,18 +79,33 @@ static bool isSuitableForBSS(const GlobalVariable *GV) {
   return true;
 }
 
-static bool isConstantString(const Constant *C) {
+/// IsNullTerminatedString - Return true if the specified constant (which is
+/// known to have a type that is an array of 1/2/4 byte elements) ends with a
+/// nul value and contains no other nuls in it.
+static bool IsNullTerminatedString(const Constant *C) {
+  const ArrayType *ATy = cast<ArrayType>(C->getType());
+  
   // First check: is we have constant array of i8 terminated with zero
-  const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
-  // Check, if initializer is a null-terminated string
-  if (CVA && CVA->isCString())
+  if (const ConstantArray *CVA = dyn_cast<ConstantArray>(C)) {
+    if (ATy->getNumElements() == 0) return false;
+
+    ConstantInt *Null =
+      dyn_cast<ConstantInt>(CVA->getOperand(ATy->getNumElements()-1));
+    if (Null == 0 || Null->getZExtValue() != 0)
+      return false; // Not null terminated.
+    
+    // Verify that the null doesn't occur anywhere else in the string.
+    for (unsigned i = 0, e = ATy->getNumElements()-1; i != e; ++i)
+      // Reject constantexpr elements etc.
+      if (!isa<ConstantInt>(CVA->getOperand(i)) ||
+          CVA->getOperand(i) == Null)
+        return false;
     return true;
+  }
 
   // Another possibility: [1 x i8] zeroinitializer
   if (isa<ConstantAggregateZero>(C))
-    if (const ArrayType *Ty = dyn_cast<ArrayType>(C->getType()))
-      return (Ty->getElementType() == Type::Int8Ty &&
-              Ty->getNumElements() == 1);
+    return ATy->getNumElements() == 1;
 
   return false;
 }
@@ -133,11 +148,23 @@ static SectionKind SectionKindForGlobal(const GlobalValue *GV,
     default: llvm_unreachable("unknown relocation info kind");
     case Constant::NoRelocation:
       // If initializer is a null-terminated string, put it in a "cstring"
-      // section if the target has it.
-      if (isConstantString(C))
-        return SectionKind::getMergeable1ByteCString();
-      
-      // FIXME: Detect 2/4 byte strings.
+      // section of the right width.
+      if (const ArrayType *ATy = dyn_cast<ArrayType>(C->getType())) {
+        if (const IntegerType *ITy = 
+              dyn_cast<IntegerType>(ATy->getElementType())) {
+          if ((ITy->getBitWidth() == 8 || ITy->getBitWidth() == 16 ||
+               ITy->getBitWidth() == 32) &&
+              IsNullTerminatedString(C)) {
+            if (ITy->getBitWidth() == 8)
+              return SectionKind::getMergeable1ByteCString();
+            if (ITy->getBitWidth() == 16)
+              return SectionKind::getMergeable2ByteCString();
+                                         
+            assert(ITy->getBitWidth() == 32 && "Unknown width");
+            return SectionKind::getMergeable4ByteCString();
+          }
+        }
+      }
         
       // Otherwise, just drop it into a mergable constant section.  If we have
       // a section for this size, use it, otherwise use the arbitrary sized
index a674a3e..4f4c4bc 100644 (file)
 ; DARWIN:_G6:
 ; DARWIN:  .ascii "\001"
 
+
+@G7 = constant [10 x i8] c"abcdefghi\00"
+
+; DARWIN:      .cstring
+; DARWIN:      .globl _G7
+; DARWIN: _G7:
+; DARWIN:      .asciz  "abcdefghi"
+
+; LINUX:       .section                .rodata.str1.1,"aMS",@progbits,1
+; LINUX:       .globl G7
+; LINUX: G7:
+; LINUX:       .asciz  "abcdefghi"
+
+
+@G8 = constant [4 x i16] [ i16 1, i16 2, i16 3, i16 0 ]
+
+; DARWIN:      .const
+; DARWIN:      .globl _G8
+; DARWIN: _G8:
+
+; LINUX:       .section                .rodata.str2.2,"aMS",@progbits,2
+; LINUX:       .globl G8
+; LINUX:G8:
+
+@G9 = constant [4 x i32] [ i32 1, i32 2, i32 3, i32 0 ]
+
+; ARWIN:       .const   [[ already in const section]]
+; DARWIN:      .globl _G9
+; DARWIN: _G9:
+
+; LINUX:       .section                .rodata.str4.4,"aMS",@progbits,4
+; LINUX:       .globl G9
+; LINUX:G9
+
+
+