20
20
#include " clang/AST/DeclCXX.h"
21
21
#include " clang/AST/DeclObjC.h"
22
22
#include " clang/AST/DeclTemplate.h"
23
+ #include " clang/AST/Expr.h"
23
24
#include " clang/AST/ExprCXX.h"
24
25
#include " clang/AST/VTableBuilder.h"
25
26
#include " clang/Basic/ABI.h"
26
27
#include " clang/Basic/DiagnosticOptions.h"
27
28
#include " clang/Basic/TargetInfo.h"
28
29
#include " llvm/ADT/StringExtras.h"
29
30
#include " llvm/ADT/StringMap.h"
31
+ #include " llvm/Support/MathExtras.h"
30
32
31
33
using namespace clang ;
32
34
@@ -93,6 +95,7 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
93
95
MicrosoftMangleContextImpl (ASTContext &Context, DiagnosticsEngine &Diags)
94
96
: MicrosoftMangleContext(Context, Diags) {}
95
97
bool shouldMangleCXXName (const NamedDecl *D) override ;
98
+ bool shouldMangleStringLiteral (const StringLiteral *SL) override ;
96
99
void mangleCXXName (const NamedDecl *D, raw_ostream &Out) override ;
97
100
void mangleVirtualMemPtrThunk (const CXXMethodDecl *MD, raw_ostream &) override ;
98
101
void mangleThunk (const CXXMethodDecl *MD, const ThunkInfo &Thunk,
@@ -118,6 +121,7 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
118
121
void mangleDynamicInitializer (const VarDecl *D, raw_ostream &Out) override ;
119
122
void mangleDynamicAtExitDestructor (const VarDecl *D,
120
123
raw_ostream &Out) override ;
124
+ void mangleStringLiteral (const StringLiteral *SL, raw_ostream &Out) override ;
121
125
bool getNextDiscriminator (const NamedDecl *ND, unsigned &disc) {
122
126
// Lambda closure types are already numbered.
123
127
if (isLambda (ND))
@@ -321,6 +325,13 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
321
325
return true ;
322
326
}
323
327
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
+
324
335
void MicrosoftCXXNameMangler::mangle (const NamedDecl *D,
325
336
StringRef Prefix) {
326
337
// MSVC doesn't mangle C++ names the same way it mangles extern "C" names.
@@ -2315,6 +2326,169 @@ MicrosoftMangleContextImpl::mangleDynamicAtExitDestructor(const VarDecl *D,
2315
2326
mangleInitFiniStub (D, Out, ' F' );
2316
2327
}
2317
2328
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
+
2318
2492
MicrosoftMangleContext *
2319
2493
MicrosoftMangleContext::create (ASTContext &Context, DiagnosticsEngine &Diags) {
2320
2494
return new MicrosoftMangleContextImpl (Context, Diags);
0 commit comments