Emit wide string literals with the appropriate alignment.

Patch by Craig Topper and Sundeep!

llvm-svn: 136856
This commit is contained in:
John McCall 2011-08-04 01:03:22 +00:00
parent e4df09f7ba
commit 9b24df470d
3 changed files with 37 additions and 25 deletions

View File

@ -1923,7 +1923,10 @@ llvm::Constant *
CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) {
// FIXME: This can be more efficient.
// FIXME: We shouldn't need to bitcast the constant in the wide string case.
llvm::Constant *C = GetAddrOfConstantString(GetStringForStringLiteral(S));
CharUnits Align = getContext().getTypeAlignInChars(S->getType());
llvm::Constant *C = GetAddrOfConstantString(GetStringForStringLiteral(S),
/* GlobalName */ 0,
Align.getQuantity());
if (S->isWide() || S->isUTF16() || S->isUTF32()) {
llvm::Type *DestTy =
llvm::PointerType::getUnqual(getTypes().ConvertType(S->getType()));
@ -1944,10 +1947,11 @@ CodeGenModule::GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *E) {
/// GenerateWritableString -- Creates storage for a string literal.
static llvm::Constant *GenerateStringLiteral(StringRef str,
static llvm::GlobalVariable *GenerateStringLiteral(StringRef str,
bool constant,
CodeGenModule &CGM,
const char *GlobalName) {
const char *GlobalName,
unsigned Alignment) {
// Create Constant for this string literal. Don't add a '\0'.
llvm::Constant *C =
llvm::ConstantArray::get(CGM.getLLVMContext(), str, false);
@ -1957,7 +1961,7 @@ static llvm::Constant *GenerateStringLiteral(StringRef str,
new llvm::GlobalVariable(CGM.getModule(), C->getType(), constant,
llvm::GlobalValue::PrivateLinkage,
C, GlobalName);
GV->setAlignment(1);
GV->setAlignment(Alignment);
GV->setUnnamedAddr(true);
return GV;
}
@ -1971,7 +1975,8 @@ static llvm::Constant *GenerateStringLiteral(StringRef str,
///
/// The result has pointer to array type.
llvm::Constant *CodeGenModule::GetAddrOfConstantString(StringRef Str,
const char *GlobalName) {
const char *GlobalName,
unsigned Alignment) {
bool IsConstant = !Features.WritableStrings;
// Get the default prefix if a name wasn't specified.
@ -1980,27 +1985,32 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantString(StringRef Str,
// Don't share any string literals if strings aren't constant.
if (!IsConstant)
return GenerateStringLiteral(Str, false, *this, GlobalName);
return GenerateStringLiteral(Str, false, *this, GlobalName, Alignment);
llvm::StringMapEntry<llvm::Constant *> &Entry =
llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
ConstantStringMap.GetOrCreateValue(Str);
if (Entry.getValue())
return Entry.getValue();
if (llvm::GlobalVariable *GV = Entry.getValue()) {
if (Alignment > GV->getAlignment()) {
GV->setAlignment(Alignment);
}
return GV;
}
// Create a global variable for this.
llvm::Constant *C = GenerateStringLiteral(Str, true, *this, GlobalName);
Entry.setValue(C);
return C;
llvm::GlobalVariable *GV = GenerateStringLiteral(Str, true, *this, GlobalName, Alignment);
Entry.setValue(GV);
return GV;
}
/// GetAddrOfConstantCString - Returns a pointer to a character
/// array containing the literal and a terminating '\0'
/// character. The result has pointer to array type.
llvm::Constant *CodeGenModule::GetAddrOfConstantCString(const std::string &Str,
const char *GlobalName){
const char *GlobalName,
unsigned Alignment) {
StringRef StrWithNull(Str.c_str(), Str.size() + 1);
return GetAddrOfConstantString(StrWithNull, GlobalName);
return GetAddrOfConstantString(StrWithNull, GlobalName, Alignment);
}
/// EmitObjCPropertyImplementations - Emit information for synthesized

View File

@ -263,7 +263,7 @@ class CodeGenModule : public CodeGenTypeCache {
std::vector<llvm::Constant*> Annotations;
llvm::StringMap<llvm::Constant*> CFConstantStringMap;
llvm::StringMap<llvm::Constant*> ConstantStringMap;
llvm::StringMap<llvm::GlobalVariable*> ConstantStringMap;
llvm::DenseMap<const Decl*, llvm::Value*> StaticLocalDeclMap;
/// CXXGlobalInits - Global variables with initializers that need to run
@ -545,7 +545,8 @@ public:
/// \param GlobalName If provided, the name to use for the global
/// (if one is created).
llvm::Constant *GetAddrOfConstantString(StringRef Str,
const char *GlobalName=0);
const char *GlobalName=0,
unsigned Alignment=1);
/// GetAddrOfConstantCString - Returns a pointer to a character array
/// containing the literal and a terminating '\0' character. The result has
@ -554,7 +555,8 @@ public:
/// \param GlobalName If provided, the name to use for the global (if one is
/// created).
llvm::Constant *GetAddrOfConstantCString(const std::string &str,
const char *GlobalName=0);
const char *GlobalName=0,
unsigned Alignment=1);
/// GetAddrOfCXXConstructor - Return the address of the constructor of the
/// given type.

View File

@ -14,26 +14,26 @@ int main() {
// CHECK-CPP0X: internal unnamed_addr constant [10 x i8] c"\E1\84\A0\C8\A0\F4\82\80\B0\00", align 1
char b[10] = "\u1120\u0220\U00102030";
// CHECK-C: private unnamed_addr constant [12 x i8] c"A\00\00\00B\00\00\00\00\00\00\00", align 1
// CHECK-CPP0X: private unnamed_addr constant [12 x i8] c"A\00\00\00B\00\00\00\00\00\00\00", align 1
// CHECK-C: private unnamed_addr constant [12 x i8] c"A\00\00\00B\00\00\00\00\00\00\00", align 4
// CHECK-CPP0X: private unnamed_addr constant [12 x i8] c"A\00\00\00B\00\00\00\00\00\00\00", align 4
const wchar_t *foo = L"AB";
// CHECK-C: private unnamed_addr constant [12 x i8] c"4\12\00\00\0B\F0\10\00\00\00\00\00", align 1
// CHECK-CPP0X: private unnamed_addr constant [12 x i8] c"4\12\00\00\0B\F0\10\00\00\00\00\00", align 1
// CHECK-C: private unnamed_addr constant [12 x i8] c"4\12\00\00\0B\F0\10\00\00\00\00\00", align 4
// CHECK-CPP0X: private unnamed_addr constant [12 x i8] c"4\12\00\00\0B\F0\10\00\00\00\00\00", align 4
const wchar_t *bar = L"\u1234\U0010F00B";
#if __cplusplus >= 201103L
// CHECK-CPP0X: private unnamed_addr constant [12 x i8] c"C\00\00\00D\00\00\00\00\00\00\00", align 1
// CHECK-CPP0X: private unnamed_addr constant [12 x i8] c"C\00\00\00D\00\00\00\00\00\00\00", align 4
const char32_t *c = U"CD";
// CHECK-CPP0X: private unnamed_addr constant [12 x i8] c"5\12\00\00\0C\F0\10\00\00\00\00\00", align 1
// CHECK-CPP0X: private unnamed_addr constant [12 x i8] c"5\12\00\00\0C\F0\10\00\00\00\00\00", align 4
const char32_t *d = U"\u1235\U0010F00C";
// CHECK-CPP0X: private unnamed_addr constant [6 x i8] c"E\00F\00\00\00", align 1
// CHECK-CPP0X: private unnamed_addr constant [6 x i8] c"E\00F\00\00\00", align 2
const char16_t *e = u"EF";
// This should convert to utf16.
// CHECK-CPP0X: private unnamed_addr constant [10 x i8] c" \11 \02\C8\DB0\DC\00\00", align 1
// CHECK-CPP0X: private unnamed_addr constant [10 x i8] c" \11 \02\C8\DB0\DC\00\00", align 2
const char16_t *f = u"\u1120\u0220\U00102030";
// CHECK-CPP0X: private unnamed_addr constant [4 x i8] c"def\00", align 1