Get MCSymbol out of the mangling business, and move all the logic
to Mangler.  Now MCSymbol just decides whether to slap quotes around
a symbol when printing it.

This also fixes some weirdness where two MCSymbols could be created
for the same symbol, if one needed to be mangled and got mangled to
the other one.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@93690 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp
index 7fd54ad..6a7643a 100644
--- a/lib/Target/CBackend/CBackend.cpp
+++ b/lib/Target/CBackend/CBackend.cpp
@@ -352,10 +352,9 @@
 
 
 static std::string Mangle(const std::string &S) {
-  std::string Result;
-  raw_string_ostream OS(Result);
-  MCSymbol::printMangledName(S, OS, 0);
-  return OS.str();
+  SmallString<52> Result;
+  Mangler::appendMangledName(Result, S, 0);
+  return std::string(Result.begin(), Result.end());
 }
 
 
@@ -1452,7 +1451,7 @@
   if (const GlobalValue *GV = dyn_cast<GlobalValue>(Operand)) {
     SmallString<128> Str;
     Mang->getNameWithPrefix(Str, GV, false);
-    return Mangle(Str.str().str());
+    return Str.str().str();
   }
     
   std::string Name = Operand->getName();
diff --git a/lib/Target/Mangler.cpp b/lib/Target/Mangler.cpp
index 5579bfc..826f950 100644
--- a/lib/Target/Mangler.cpp
+++ b/lib/Target/Mangler.cpp
@@ -18,6 +18,79 @@
 #include "llvm/ADT/Twine.h"
 using namespace llvm;
 
+static bool isAcceptableChar(char C) {
+  if ((C < 'a' || C > 'z') &&
+      (C < 'A' || C > 'Z') &&
+      (C < '0' || C > '9') &&
+      C != '_' && C != '$' && C != '.' && C != '@')
+    return false;
+  return true;
+}
+
+static char HexDigit(int V) {
+  return V < 10 ? V+'0' : V+'A'-10;
+}
+
+static void MangleLetter(SmallVectorImpl<char> &OutName, unsigned char C) {
+  OutName.push_back('_');
+  OutName.push_back(HexDigit(C >> 4));
+  OutName.push_back(HexDigit(C & 15));
+  OutName.push_back('_');
+}
+
+/// NameNeedsEscaping - Return true if the identifier \arg Str needs quotes
+/// for this assembler.
+static bool NameNeedsEscaping(StringRef Str, const MCAsmInfo &MAI) {
+  assert(!Str.empty() && "Cannot create an empty MCSymbol");
+  
+  // If the first character is a number and the target does not allow this, we
+  // need quotes.
+  if (!MAI.doesAllowNameToStartWithDigit() && Str[0] >= '0' && Str[0] <= '9')
+    return true;
+  
+  // If any of the characters in the string is an unacceptable character, force
+  // quotes.
+  for (unsigned i = 0, e = Str.size(); i != e; ++i)
+    if (!isAcceptableChar(Str[i]))
+      return true;
+  return false;
+}
+
+/// appendMangledName - Add the specified string in mangled form if it uses
+/// any unusual characters.
+void Mangler::appendMangledName(SmallVectorImpl<char> &OutName, StringRef Str,
+                                const MCAsmInfo *MAI) {
+  // The first character is not allowed to be a number unless the target
+  // explicitly allows it.
+  if ((MAI == 0 || !MAI->doesAllowNameToStartWithDigit()) &&
+      Str[0] >= '0' && Str[0] <= '9') {
+    MangleLetter(OutName, Str[0]);
+    Str = Str.substr(1);
+  }
+  
+  for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+    if (!isAcceptableChar(Str[i]))
+      MangleLetter(OutName, Str[i]);
+    else
+      OutName.push_back(Str[i]);
+  }
+}
+
+
+/// appendMangledQuotedName - On systems that support quoted symbols, we still
+/// have to escape some (obscure) characters like " and \n which would break the
+/// assembler's lexing.
+static void appendMangledQuotedName(SmallVectorImpl<char> &OutName,
+                                   StringRef Str) {
+  for (unsigned i = 0, e = Str.size(); i != e; ++i) {
+    if (Str[i] == '"' || Str[i] == '\n')
+      MangleLetter(OutName, Str[i]);
+    else
+      OutName.push_back(Str[i]);
+  }
+}
+
+
 /// getNameWithPrefix - Fill OutName with the name of the appropriate prefix
 /// and the specified name as the global variable name.  GVName must not be
 /// empty.
@@ -28,7 +101,9 @@
   assert(!Name.empty() && "getNameWithPrefix requires non-empty name");
   
   // If the global name is not led with \1, add the appropriate prefixes.
-  if (Name[0] != '\1') {
+  if (Name[0] == '\1') {
+    Name = Name.substr(1);
+  } else {
     if (PrefixTy == Mangler::Private) {
       const char *Prefix = MAI.getPrivateGlobalPrefix();
       OutName.append(Prefix, Prefix+strlen(Prefix));
@@ -44,11 +119,27 @@
       OutName.push_back(Prefix[0]);  // Common, one character prefix.
     else
       OutName.append(Prefix, Prefix+strlen(Prefix)); // Arbitrary length prefix.
-  } else {
-    Name = Name.substr(1);
   }
   
-  OutName.append(Name.begin(), Name.end());
+  // If this is a simple string that doesn't need escaping, just append it.
+  if (!NameNeedsEscaping(Name, MAI) ||
+      // If quotes are supported, they can be used unless the string contains
+      // a quote or newline.
+      (MAI.doesAllowQuotesInName() &&
+       Name.find_first_of("\n\"") == StringRef::npos)) {
+    OutName.append(Name.begin(), Name.end());
+    return;
+  }
+  
+  // On systems that do not allow quoted names, we need to mangle most
+  // strange characters.
+  if (!MAI.doesAllowQuotesInName())
+    return appendMangledName(OutName, Name, &MAI);
+  
+  // Okay, the system allows quoted strings.  We can quote most anything, the
+  // only characters that need escaping are " and \n.
+  assert(Name.find_first_of("\n\"") != StringRef::npos);
+  return appendMangledQuotedName(OutName, Name);
 }
 
 
diff --git a/lib/Target/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp
index 39c90cd..93cb420 100644
--- a/lib/Target/TargetLoweringObjectFile.cpp
+++ b/lib/Target/TargetLoweringObjectFile.cpp
@@ -579,18 +579,11 @@
   // into a 'uniqued' section name, create and return the section now.
   if (GV->isWeakForLinker()) {
     const char *Prefix = getSectionPrefixForUniqueGlobal(Kind);
-    SmallString<128> Name, MangledName;
+    SmallString<128> Name;
     Name.append(Prefix, Prefix+strlen(Prefix));
     Mang->getNameWithPrefix(Name, GV, false);
-    
-    raw_svector_ostream OS(MangledName);
-    MCSymbol::printMangledName(Name, OS, 0);
-    OS.flush();
-    
-    return getELFSection(MangledName.str(),
-                         getELFSectionType(MangledName.str(), Kind),
-                         getELFSectionFlags(Kind),
-                         Kind);
+    return getELFSection(Name.str(), getELFSectionType(Name.str(), Kind),
+                         getELFSectionFlags(Kind), Kind);
   }
 
   if (Kind.isText()) return TextSection;