summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CodeGenModule.cpp
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2012-03-30 00:26:17 +0000
committerBill Wendling <isanbard@gmail.com>2012-03-30 00:26:17 +0000
commit84392d0edc7127f868d3c97484ffc9d789c317ff (patch)
treee573e4eba6428d16f96afd586711fe4848eb6949 /lib/CodeGen/CodeGenModule.cpp
parentb085d898bdfe35097eba45f4072b0f6865f561dc (diff)
The UTF16 string referenced by a CFString should go into the __TEXT,__ustring
section. A 'normal' string will go into the __TEXT,__const section, but this isn't good for UTF16 strings. The __ustring section allows for coalescing, among other niceties (such as allowing the linker to easily split up strings). Instead of outputting the UTF16 string as a series of bytes, output it as a series of shorts. The back-end will then nicely place the UTF16 string into the correct section, because it's a mensch. <rdar://problem/10655949> git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153710 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CodeGenModule.cpp')
-rw-r--r--lib/CodeGen/CodeGenModule.cpp50
1 files changed, 24 insertions, 26 deletions
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 6fa33b6c12..c9f1066032 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -1903,8 +1903,10 @@ GetConstantCFStringEntry(llvm::StringMap<llvm::Constant*> &Map,
return Map.GetOrCreateValue(String);
}
- // Otherwise, convert the UTF8 literals into a byte string.
- SmallVector<UTF16, 128> ToBuf(NumBytes);
+ // Otherwise, convert the UTF8 literals into a string of shorts.
+ IsUTF16 = true;
+
+ SmallVector<UTF16, 128> ToBuf(NumBytes + 1); // +1 for ending nulls.
const UTF8 *FromPtr = (UTF8 *)String.data();
UTF16 *ToPtr = &ToBuf[0];
@@ -1915,28 +1917,11 @@ GetConstantCFStringEntry(llvm::StringMap<llvm::Constant*> &Map,
// ConvertUTF8toUTF16 returns the length in ToPtr.
StringLength = ToPtr - &ToBuf[0];
- // Render the UTF-16 string into a byte array and convert to the target byte
- // order.
- //
- // FIXME: This isn't something we should need to do here.
- SmallString<128> AsBytes;
- AsBytes.reserve(StringLength * 2);
- for (unsigned i = 0; i != StringLength; ++i) {
- unsigned short Val = ToBuf[i];
- if (TargetIsLSB) {
- AsBytes.push_back(Val & 0xFF);
- AsBytes.push_back(Val >> 8);
- } else {
- AsBytes.push_back(Val >> 8);
- AsBytes.push_back(Val & 0xFF);
- }
- }
- // Append one extra null character, the second is automatically added by our
- // caller.
- AsBytes.push_back(0);
-
- IsUTF16 = true;
- return Map.GetOrCreateValue(StringRef(AsBytes.data(), AsBytes.size()));
+ // Add an explicit null.
+ *ToPtr = 0;
+ return Map.
+ GetOrCreateValue(StringRef(reinterpret_cast<const char *>(ToBuf.data()),
+ (StringLength + 1) * 2));
}
static llvm::StringMapEntry<llvm::Constant*> &
@@ -1990,8 +1975,15 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
llvm::ConstantInt::get(Ty, 0x07C8);
// String pointer.
- llvm::Constant *C = llvm::ConstantDataArray::getString(VMContext,
- Entry.getKey());
+ llvm::Constant *C = 0;
+ if (isUTF16) {
+ ArrayRef<uint16_t> Arr =
+ llvm::makeArrayRef<uint16_t>((uint16_t*)Entry.getKey().data(),
+ Entry.getKey().size() / 2);
+ C = llvm::ConstantDataArray::get(VMContext, Arr);
+ } else {
+ C = llvm::ConstantDataArray::getString(VMContext, Entry.getKey());
+ }
llvm::GlobalValue::LinkageTypes Linkage;
if (isUTF16)
@@ -2016,8 +2008,14 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
CharUnits Align = getContext().getTypeAlignInChars(getContext().CharTy);
GV->setAlignment(Align.getQuantity());
}
+
+ // String.
Fields[2] = llvm::ConstantExpr::getGetElementPtr(GV, Zeros);
+ if (isUTF16)
+ // Cast the UTF16 string to the correct type.
+ Fields[2] = llvm::ConstantExpr::getBitCast(Fields[2], Int8PtrTy);
+
// String length.
Ty = getTypes().ConvertType(getContext().LongTy);
Fields[3] = llvm::ConstantInt::get(Ty, StringLength);