Skip to content

Commit 58e5bee

Browse files
committedMar 24, 2014
MS ABI: Eliminate Duplicate Strings
COFF doesn't have mergeable sections so LLVM/clang's normal tactics for string deduplication will not have any effect. To remedy this we place each string inside it's own section and mark the section as IMAGE_COMDAT_SELECT_ANY. However, we can only do this if the string has an external name that we can generate from it's contents. To be compatible with MSVC, we must use their scheme. Otherwise identical strings in translation units from clang may not be deduplicated with translation units in MSVC. This fixes PR18248. N.B. We will not attempt to do anything with a string literal which is not of type 'char' or 'wchar_t' because their compiler does not support unicode string literals as of this date. Further, we avoid doing this if either -fwritable-strings or -fsanitize=address are present. This reverts commit r204596. llvm-svn: 204675
1 parent c89450e commit 58e5bee

9 files changed

+988
-29
lines changed
 

‎clang/include/clang/AST/Mangle.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ namespace clang {
3131
class FunctionDecl;
3232
class NamedDecl;
3333
class ObjCMethodDecl;
34-
class VarDecl;
34+
class StringLiteral;
3535
struct ThisAdjustment;
3636
struct ThunkInfo;
37+
class VarDecl;
3738

3839
/// MangleBuffer - a convenient class for storing a name which is
3940
/// either the result of a mangling or is a constant string with
@@ -117,6 +118,7 @@ class MangleContext {
117118

118119
bool shouldMangleDeclName(const NamedDecl *D);
119120
virtual bool shouldMangleCXXName(const NamedDecl *D) = 0;
121+
virtual bool shouldMangleStringLiteral(const StringLiteral *SL) = 0;
120122

121123
// FIXME: consider replacing raw_ostream & with something like SmallString &.
122124
void mangleName(const NamedDecl *D, raw_ostream &);
@@ -135,6 +137,7 @@ class MangleContext {
135137
raw_ostream &) = 0;
136138
virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
137139
raw_ostream &) = 0;
140+
virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0;
138141

139142
void mangleGlobalBlock(const BlockDecl *BD,
140143
const NamedDecl *ID,

‎clang/lib/AST/ItaniumMangle.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "clang/AST/DeclCXX.h"
2222
#include "clang/AST/DeclObjC.h"
2323
#include "clang/AST/DeclTemplate.h"
24+
#include "clang/AST/Expr.h"
2425
#include "clang/AST/ExprCXX.h"
2526
#include "clang/AST/ExprObjC.h"
2627
#include "clang/AST/TypeLoc.h"
@@ -126,6 +127,9 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
126127
/// @{
127128

128129
bool shouldMangleCXXName(const NamedDecl *D) override;
130+
bool shouldMangleStringLiteral(const StringLiteral *) override {
131+
return false;
132+
}
129133
void mangleCXXName(const NamedDecl *D, raw_ostream &) override;
130134
void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk,
131135
raw_ostream &) override;
@@ -153,6 +157,8 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
153157
void mangleItaniumThreadLocalWrapper(const VarDecl *D,
154158
raw_ostream &) override;
155159

160+
void mangleStringLiteral(const StringLiteral *, raw_ostream &) override;
161+
156162
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
157163
// Lambda closure types are already numbered.
158164
if (isLambda(ND))
@@ -3774,6 +3780,10 @@ void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out) {
37743780
mangleCXXRTTIName(Ty, Out);
37753781
}
37763782

3783+
void ItaniumMangleContextImpl::mangleStringLiteral(const StringLiteral *, raw_ostream &) {
3784+
llvm_unreachable("Can't mangle string literals");
3785+
}
3786+
37773787
ItaniumMangleContext *
37783788
ItaniumMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) {
37793789
return new ItaniumMangleContextImpl(Context, Diags);

‎clang/lib/AST/MicrosoftMangle.cpp

+174
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020
#include "clang/AST/DeclCXX.h"
2121
#include "clang/AST/DeclObjC.h"
2222
#include "clang/AST/DeclTemplate.h"
23+
#include "clang/AST/Expr.h"
2324
#include "clang/AST/ExprCXX.h"
2425
#include "clang/AST/VTableBuilder.h"
2526
#include "clang/Basic/ABI.h"
2627
#include "clang/Basic/DiagnosticOptions.h"
2728
#include "clang/Basic/TargetInfo.h"
2829
#include "llvm/ADT/StringExtras.h"
2930
#include "llvm/ADT/StringMap.h"
31+
#include "llvm/Support/MathExtras.h"
3032

3133
using namespace clang;
3234

@@ -93,6 +95,7 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
9395
MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags)
9496
: MicrosoftMangleContext(Context, Diags) {}
9597
bool shouldMangleCXXName(const NamedDecl *D) override;
98+
bool shouldMangleStringLiteral(const StringLiteral *SL) override;
9699
void mangleCXXName(const NamedDecl *D, raw_ostream &Out) override;
97100
void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, raw_ostream &) override;
98101
void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk,
@@ -118,6 +121,7 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
118121
void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override;
119122
void mangleDynamicAtExitDestructor(const VarDecl *D,
120123
raw_ostream &Out) override;
124+
void mangleStringLiteral(const StringLiteral *SL, raw_ostream &Out) override;
121125
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
122126
// Lambda closure types are already numbered.
123127
if (isLambda(ND))
@@ -321,6 +325,13 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
321325
return true;
322326
}
323327

328+
bool
329+
MicrosoftMangleContextImpl::shouldMangleStringLiteral(const StringLiteral *SL) {
330+
return SL->isAscii() || SL->isWide();
331+
// TODO: This needs to be updated when MSVC gains support for Unicode
332+
// literals.
333+
}
334+
324335
void MicrosoftCXXNameMangler::mangle(const NamedDecl *D,
325336
StringRef Prefix) {
326337
// MSVC doesn't mangle C++ names the same way it mangles extern "C" names.
@@ -2315,6 +2326,169 @@ MicrosoftMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D,
23152326
mangleInitFiniStub(D, Out, 'F');
23162327
}
23172328

2329+
void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
2330+
raw_ostream &Out) {
2331+
// <char-type> ::= 0 # char
2332+
// ::= 1 # wchar_t
2333+
// ::= ??? # char16_t/char32_t will need a mangling too...
2334+
//
2335+
// <literal-length> ::= <non-negative integer> # the length of the literal
2336+
//
2337+
// <encoded-crc> ::= <hex digit>+ @ # crc of the literal including
2338+
// # null-terminator
2339+
//
2340+
// <encoded-string> ::= <simple character> # uninteresting character
2341+
// ::= '?$' <hex digit> <hex digit> # these two nibbles
2342+
// # encode the byte for the
2343+
// # character
2344+
// ::= '?' [a-z] # \xe1 - \xfa
2345+
// ::= '?' [A-Z] # \xc1 - \xda
2346+
// ::= '?' [0-9] # [,/\:. \n\t'-]
2347+
//
2348+
// <literal> ::= '??_C@_' <char-type> <literal-length> <encoded-crc>
2349+
// <encoded-string> '@'
2350+
MicrosoftCXXNameMangler Mangler(*this, Out);
2351+
Mangler.getStream() << "\01??_C@_";
2352+
2353+
// <char-type>: The "kind" of string literal is encoded into the mangled name.
2354+
// TODO: This needs to be updated when MSVC gains support for unicode
2355+
// literals.
2356+
if (SL->isAscii())
2357+
Mangler.getStream() << '0';
2358+
else if (SL->isWide())
2359+
Mangler.getStream() << '1';
2360+
else
2361+
llvm_unreachable("unexpected string literal kind!");
2362+
2363+
// <literal-length>: The next part of the mangled name consists of the length
2364+
// of the string.
2365+
// The StringLiteral does not consider the NUL terminator byte(s) but the
2366+
// mangling does.
2367+
// N.B. The length is in terms of bytes, not characters.
2368+
Mangler.mangleNumber(SL->getByteLength() + SL->getCharByteWidth());
2369+
2370+
// We will use the "Rocksoft^tm Model CRC Algorithm" to describe the
2371+
// properties of our CRC:
2372+
// Width : 32
2373+
// Poly : 04C11DB7
2374+
// Init : FFFFFFFF
2375+
// RefIn : True
2376+
// RefOut : True
2377+
// XorOut : 00000000
2378+
// Check : 340BC6D9
2379+
uint32_t CRC = 0xFFFFFFFFU;
2380+
2381+
auto UpdateCRC = [&CRC](char Byte) {
2382+
for (unsigned i = 0; i < 8; ++i) {
2383+
bool Bit = CRC & 0x80000000U;
2384+
if (Byte & (1U << i))
2385+
Bit = !Bit;
2386+
CRC <<= 1;
2387+
if (Bit)
2388+
CRC ^= 0x04C11DB7U;
2389+
}
2390+
};
2391+
2392+
// CRC all the bytes of the StringLiteral.
2393+
for (char Byte : SL->getBytes())
2394+
UpdateCRC(Byte);
2395+
2396+
// The NUL terminator byte(s) were not present earlier,
2397+
// we need to manually process those bytes into the CRC.
2398+
for (unsigned NullTerminator = 0; NullTerminator < SL->getCharByteWidth();
2399+
++NullTerminator)
2400+
UpdateCRC('\x00');
2401+
2402+
// The literature refers to the process of reversing the bits in the final CRC
2403+
// output as "reflection".
2404+
CRC = llvm::reverseBits(CRC);
2405+
2406+
// <encoded-crc>: The CRC is encoded utilizing the standard number mangling
2407+
// scheme.
2408+
Mangler.mangleNumber(CRC);
2409+
2410+
// <encoded-crc>: The mangled name also contains the first 32 _characters_
2411+
// (including null-terminator bytes) of the StringLiteral.
2412+
// Each character is encoded by splitting them into bytes and then encoding
2413+
// the constituent bytes.
2414+
auto MangleByte = [&Mangler](char Byte) {
2415+
// There are five different manglings for characters:
2416+
// - [a-zA-Z0-9_$]: A one-to-one mapping.
2417+
// - ?[a-z]: The range from \xe1 to \xfa.
2418+
// - ?[A-Z]: The range from \xc1 to \xda.
2419+
// - ?[0-9]: The set of [,/\:. \n\t'-].
2420+
// - ?$XX: A fallback which maps nibbles.
2421+
if ((Byte >= 'a' && Byte <= 'z') || (Byte >= 'A' && Byte <= 'Z') ||
2422+
(Byte >= '0' && Byte <= '9') || Byte == '_' || Byte == '$') {
2423+
Mangler.getStream() << Byte;
2424+
} else if (Byte >= '\xe1' && Byte <= '\xfa') {
2425+
Mangler.getStream() << '?' << static_cast<char>('a' + (Byte - '\xe1'));
2426+
} else if (Byte >= '\xc1' && Byte <= '\xda') {
2427+
Mangler.getStream() << '?' << static_cast<char>('A' + (Byte - '\xc1'));
2428+
} else {
2429+
switch (Byte) {
2430+
case ',':
2431+
Mangler.getStream() << "?0";
2432+
break;
2433+
case '/':
2434+
Mangler.getStream() << "?1";
2435+
break;
2436+
case '\\':
2437+
Mangler.getStream() << "?2";
2438+
break;
2439+
case ':':
2440+
Mangler.getStream() << "?3";
2441+
break;
2442+
case '.':
2443+
Mangler.getStream() << "?4";
2444+
break;
2445+
case ' ':
2446+
Mangler.getStream() << "?5";
2447+
break;
2448+
case '\n':
2449+
Mangler.getStream() << "?6";
2450+
break;
2451+
case '\t':
2452+
Mangler.getStream() << "?7";
2453+
break;
2454+
case '\'':
2455+
Mangler.getStream() << "?8";
2456+
break;
2457+
case '-':
2458+
Mangler.getStream() << "?9";
2459+
break;
2460+
default:
2461+
Mangler.getStream() << "?$";
2462+
Mangler.getStream() << static_cast<char>('A' + ((Byte >> 4) & 0xf));
2463+
Mangler.getStream() << static_cast<char>('A' + (Byte & 0xf));
2464+
break;
2465+
}
2466+
}
2467+
};
2468+
2469+
auto MangleChar = [&Mangler, &MangleByte, &SL](uint32_t CodeUnit) {
2470+
if (SL->getCharByteWidth() == 1) {
2471+
MangleByte(static_cast<char>(CodeUnit));
2472+
} else if (SL->getCharByteWidth() == 2) {
2473+
MangleByte(static_cast<char>((CodeUnit >> 16) & 0xff));
2474+
MangleByte(static_cast<char>(CodeUnit & 0xff));
2475+
} else {
2476+
llvm_unreachable("unsupported CharByteWidth");
2477+
}
2478+
};
2479+
2480+
// Enforce our 32 character max.
2481+
unsigned NumCharsToMangle = std::min(32U, SL->getLength());
2482+
for (unsigned i = 0; i < NumCharsToMangle; ++i)
2483+
MangleChar(SL->getCodeUnit(i));
2484+
2485+
// Encode the NUL terminator if there is room.
2486+
if (NumCharsToMangle < 32)
2487+
MangleChar(0);
2488+
2489+
Mangler.getStream() << '@';
2490+
}
2491+
23182492
MicrosoftMangleContext *
23192493
MicrosoftMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) {
23202494
return new MicrosoftMangleContextImpl(Context, Diags);

‎clang/lib/CodeGen/CodeGenModule.cpp

+60-18
Original file line numberDiff line numberDiff line change
@@ -2572,25 +2572,67 @@ CodeGenModule::GetConstantArrayFromStringLiteral(const StringLiteral *E) {
25722572
llvm::Constant *
25732573
CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) {
25742574
CharUnits Align = getContext().getAlignOfGlobalVarInChars(S->getType());
2575-
if (S->isAscii() || S->isUTF8()) {
2576-
SmallString<64> Str(S->getString());
2577-
2578-
// Resize the string to the right size, which is indicated by its type.
2579-
const ConstantArrayType *CAT = Context.getAsConstantArrayType(S->getType());
2580-
Str.resize(CAT->getSize().getZExtValue());
2581-
return GetAddrOfConstantString(Str, /*GlobalName*/ 0, Align.getQuantity());
2575+
2576+
llvm::StringMapEntry<llvm::GlobalVariable *> *Entry = nullptr;
2577+
llvm::GlobalVariable *GV = nullptr;
2578+
if (!LangOpts.WritableStrings) {
2579+
llvm::StringMap<llvm::GlobalVariable *> *ConstantStringMap = nullptr;
2580+
switch (S->getCharByteWidth()) {
2581+
case 1:
2582+
ConstantStringMap = &Constant1ByteStringMap;
2583+
break;
2584+
case 2:
2585+
ConstantStringMap = &Constant2ByteStringMap;
2586+
break;
2587+
case 4:
2588+
ConstantStringMap = &Constant4ByteStringMap;
2589+
break;
2590+
default:
2591+
llvm_unreachable("unhandled byte width!");
2592+
}
2593+
Entry = &ConstantStringMap->GetOrCreateValue(S->getBytes());
2594+
GV = Entry->getValue();
2595+
}
2596+
2597+
if (!GV) {
2598+
SmallString<256> MangledNameBuffer;
2599+
StringRef GlobalVariableName;
2600+
llvm::GlobalValue::LinkageTypes LT;
2601+
2602+
// Mangle the string literal if the ABI allows for it. However, we cannot
2603+
// do this if we are compiling with ASan or -fwritable-strings because they
2604+
// rely on strings having normal linkage.
2605+
if (!LangOpts.WritableStrings && !SanOpts.Address &&
2606+
getCXXABI().getMangleContext().shouldMangleStringLiteral(S)) {
2607+
llvm::raw_svector_ostream Out(MangledNameBuffer);
2608+
getCXXABI().getMangleContext().mangleStringLiteral(S, Out);
2609+
Out.flush();
2610+
2611+
LT = llvm::GlobalValue::LinkOnceODRLinkage;
2612+
GlobalVariableName = MangledNameBuffer;
2613+
} else {
2614+
LT = llvm::GlobalValue::PrivateLinkage;;
2615+
GlobalVariableName = ".str";
2616+
}
2617+
2618+
// OpenCL v1.2 s6.5.3: a string literal is in the constant address space.
2619+
unsigned AddrSpace = 0;
2620+
if (getLangOpts().OpenCL)
2621+
AddrSpace = getContext().getTargetAddressSpace(LangAS::opencl_constant);
2622+
2623+
llvm::Constant *C = GetConstantArrayFromStringLiteral(S);
2624+
GV = new llvm::GlobalVariable(
2625+
getModule(), C->getType(), !LangOpts.WritableStrings, LT, C,
2626+
GlobalVariableName, /*InsertBefore=*/nullptr,
2627+
llvm::GlobalVariable::NotThreadLocal, AddrSpace);
2628+
GV->setUnnamedAddr(true);
2629+
if (Entry)
2630+
Entry->setValue(GV);
25822631
}
25832632

2584-
// FIXME: the following does not memoize wide strings.
2585-
llvm::Constant *C = GetConstantArrayFromStringLiteral(S);
2586-
llvm::GlobalVariable *GV =
2587-
new llvm::GlobalVariable(getModule(),C->getType(),
2588-
!LangOpts.WritableStrings,
2589-
llvm::GlobalValue::PrivateLinkage,
2590-
C,".str");
2633+
if (Align.getQuantity() > GV->getAlignment())
2634+
GV->setAlignment(Align.getQuantity());
25912635

2592-
GV->setAlignment(Align.getQuantity());
2593-
GV->setUnnamedAddr(true);
25942636
return GV;
25952637
}
25962638

@@ -2615,7 +2657,7 @@ static llvm::GlobalVariable *GenerateStringLiteral(StringRef str,
26152657
llvm::Constant *C =
26162658
llvm::ConstantDataArray::getString(CGM.getLLVMContext(), str, false);
26172659

2618-
// OpenCL v1.1 s6.5.3: a string literal is in the constant address space.
2660+
// OpenCL v1.2 s6.5.3: a string literal is in the constant address space.
26192661
unsigned AddrSpace = 0;
26202662
if (CGM.getLangOpts().OpenCL)
26212663
AddrSpace = CGM.getContext().getTargetAddressSpace(LangAS::opencl_constant);
@@ -2654,7 +2696,7 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantString(StringRef Str,
26542696
return GenerateStringLiteral(Str, false, *this, GlobalName, Alignment);
26552697

26562698
llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
2657-
ConstantStringMap.GetOrCreateValue(Str);
2699+
Constant1ByteStringMap.GetOrCreateValue(Str);
26582700

26592701
if (llvm::GlobalVariable *GV = Entry.getValue()) {
26602702
if (Alignment > GV->getAlignment()) {

‎clang/lib/CodeGen/CodeGenModule.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,10 @@ class CodeGenModule : public CodeGenTypeCache {
319319
llvm::StringMap<llvm::Constant*> AnnotationStrings;
320320

321321
llvm::StringMap<llvm::Constant*> CFConstantStringMap;
322-
llvm::StringMap<llvm::GlobalVariable*> ConstantStringMap;
322+
323+
llvm::StringMap<llvm::GlobalVariable *> Constant1ByteStringMap;
324+
llvm::StringMap<llvm::GlobalVariable *> Constant2ByteStringMap;
325+
llvm::StringMap<llvm::GlobalVariable *> Constant4ByteStringMap;
323326
llvm::DenseMap<const Decl*, llvm::Constant *> StaticLocalDeclMap;
324327
llvm::DenseMap<const Decl*, llvm::GlobalVariable*> StaticLocalDeclGuardMap;
325328
llvm::DenseMap<const Expr*, llvm::Constant *> MaterializedGlobalTemporaryMap;

‎clang/test/CodeGen/c-strings.c

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
1+
// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=ITANIUM
2+
// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=MSABI
23

34
// Should be 3 hello strings, two global (of different sizes), the rest are
45
// shared.
56

67
// CHECK: @align = global i8 [[ALIGN:[0-9]+]]
7-
// CHECK: @.str = private unnamed_addr constant [6 x i8] c"hello\00"
8-
// CHECK: @f1.x = internal global i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0)
8+
// ITANIUM: @.str = private unnamed_addr constant [6 x i8] c"hello\00"
9+
// MSABI: @"\01??_C@_05CJBACGMB@hello?$AA@" = linkonce_odr unnamed_addr constant [6 x i8] c"hello\00", align 1
10+
// ITANIUM: @f1.x = internal global i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0)
11+
// MSABI: @f1.x = internal global i8* getelementptr inbounds ([6 x i8]* @"\01??_C@_05CJBACGMB@hello?$AA@", i32 0, i32 0)
912
// CHECK: @f2.x = internal global [6 x i8] c"hello\00", align [[ALIGN]]
1013
// CHECK: @f3.x = internal global [8 x i8] c"hello\00\00\00", align [[ALIGN]]
11-
// CHECK: @f4.x = internal global %struct.s { i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0) }
14+
// ITANIUM: @f4.x = internal global %struct.s { i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0) }
15+
// MSABI: @f4.x = internal global %struct.s { i8* getelementptr inbounds ([6 x i8]* @"\01??_C@_05CJBACGMB@hello?$AA@", i32 0, i32 0) }
1216
// CHECK: @x = global [3 x i8] c"ola", align [[ALIGN]]
1317

1418
#if defined(__s390x__)
@@ -22,7 +26,8 @@ void bar(const char *);
2226
// CHECK-LABEL: define void @f0()
2327
void f0() {
2428
bar("hello");
25-
// CHECK: call void @bar({{.*}} @.str
29+
// ITANIUM: call void @bar({{.*}} @.str
30+
// MSABI: call void @bar({{.*}} @"\01??_C@_05CJBACGMB@hello?$AA@"
2631
}
2732

2833
// CHECK-LABEL: define void @f1()

‎clang/test/CodeGen/string-literal-short-wstring.c

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
// RUN: %clang_cc1 -x c++ -emit-llvm -fshort-wchar %s -o - | FileCheck %s
1+
// RUN: %clang_cc1 -x c++ -triple %itanium_abi_triple -emit-llvm -fshort-wchar %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=ITANIUM
2+
// RUN: %clang_cc1 -x c++ -triple %ms_abi_triple -emit-llvm -fshort-wchar %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=MSABI
23
// Runs in c++ mode so that wchar_t is available.
34

45
int main() {
56
// This should convert to utf8.
67
// CHECK: private unnamed_addr constant [10 x i8] c"\E1\84\A0\C8\A0\F4\82\80\B0\00", align 1
78
char b[10] = "\u1120\u0220\U00102030";
89

9-
// CHECK: private unnamed_addr constant [3 x i16] [i16 65, i16 66, i16 0]
10+
// ITANIUM: private unnamed_addr constant [3 x i16] [i16 65, i16 66, i16 0]
11+
// MSABI: linkonce_odr unnamed_addr constant [3 x i16] [i16 65, i16 66, i16 0]
1012
const wchar_t *foo = L"AB";
1113

1214
// This should convert to utf16.
13-
// CHECK: private unnamed_addr constant [5 x i16] [i16 4384, i16 544, i16 -9272, i16 -9168, i16 0]
15+
// ITANIUM: private unnamed_addr constant [5 x i16] [i16 4384, i16 544, i16 -9272, i16 -9168, i16 0]
16+
// MSABI: linkonce_odr unnamed_addr constant [5 x i16] [i16 4384, i16 544, i16 -9272, i16 -9168, i16 0]
1417
const wchar_t *bar = L"\u1120\u0220\U00102030";
1518

1619

‎clang/test/CodeGen/wchar-const.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ typedef __WCHAR_TYPE__ wchar_t;
1515

1616

1717
// CHECK-DAR: private unnamed_addr constant [18 x i32] [i32 84,
18-
// CHECK-WIN: private unnamed_addr constant [18 x i16] [i16 84,
18+
// CHECK-WIN: linkonce_odr unnamed_addr constant [18 x i16] [i16 84,
1919
extern void foo(const wchar_t* p);
2020
int main (int argc, const char * argv[])
2121
{

‎clang/test/CodeGenCXX/mangle-ms-string-literals.cpp

+719
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.