aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/TargetLoweringObjectFile.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-08-04 16:13:09 +0000
committerChris Lattner <sabre@nondot.org>2009-08-04 16:13:09 +0000
commit1850e5add1516e945bbabf7e456c305f4bd5cc6f (patch)
tree9659104ac92b1269a317845bb081f3976867486c /lib/Target/TargetLoweringObjectFile.cpp
parent0307a76defbe2cb0174b5e0fe77877c044ab8b4f (diff)
Add support emiting for 2/4 byte mergable strings to the ".rodata.str*"
section on ELF targets. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78066 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/TargetLoweringObjectFile.cpp')
-rw-r--r--lib/Target/TargetLoweringObjectFile.cpp51
1 files changed, 39 insertions, 12 deletions
diff --git a/lib/Target/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp
index f2c7988a08..7d8f529bb9 100644
--- a/lib/Target/TargetLoweringObjectFile.cpp
+++ b/lib/Target/TargetLoweringObjectFile.cpp
@@ -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