diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index eb594532fe0..c84babac4a9 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -26,7 +26,8 @@ namespace llvm { class raw_ostream; /// MCSymbol - Instances of this class represent a symbol name in the MC file, - /// and MCSymbols are created and unique'd by the MCContext class. + /// and MCSymbols are created and unique'd by the MCContext class. MCSymbols + /// should only be constructed with valid names for the object file. /// /// If the symbol is defined/emitted into the current translation unit, the /// Section member is set to indicate what section it lives in. Otherwise, if @@ -53,7 +54,7 @@ namespace llvm { /// typically does not survive in the .o file's symbol table. Usually /// "Lfoo" or ".foo". unsigned IsTemporary : 1; - + private: // MCContext creates and uniques these. friend class MCContext; MCSymbol(StringRef _Name, bool _IsTemporary) @@ -136,11 +137,6 @@ namespace llvm { /// dump - Print the value to stderr. void dump() const; - - /// printMangledName - Print the specified string in mangled form if it uses - /// any unusual characters. - static void printMangledName(StringRef Str, raw_ostream &OS, - const MCAsmInfo *MAI); }; } // end namespace llvm diff --git a/include/llvm/Target/Mangler.h b/include/llvm/Target/Mangler.h index 07ff7e29c0f..8caa6230435 100644 --- a/include/llvm/Target/Mangler.h +++ b/include/llvm/Target/Mangler.h @@ -18,6 +18,7 @@ #include namespace llvm { +class StringRef; class Twine; class Value; class GlobalValue; @@ -67,6 +68,11 @@ public: /// have a name, this fills in a unique name for the global. std::string getNameWithPrefix(const GlobalValue *GV, bool isImplicitlyPrivate = false); + + /// appendMangledName - Add the specified string in mangled form if it uses + /// any unusual characters. + static void appendMangledName(SmallVectorImpl &OutName, StringRef Str, + const MCAsmInfo *MAI); }; } // End llvm namespace diff --git a/lib/MC/MCSymbol.cpp b/lib/MC/MCSymbol.cpp index 265d06cceba..812ee69100b 100644 --- a/lib/MC/MCSymbol.cpp +++ b/lib/MC/MCSymbol.cpp @@ -26,14 +26,6 @@ static bool isAcceptableChar(char C) { return true; } -static char HexDigit(int V) { - return V < 10 ? V+'0' : V+'A'-10; -} - -static void MangleLetter(raw_ostream &OS, unsigned char C) { - OS << '_' << HexDigit(C >> 4) << HexDigit(C & 15) << '_'; -} - /// NameNeedsEscaping - Return true if the identifier \arg Str needs quotes /// for this assembler. static bool NameNeedsEscaping(StringRef Str, const MCAsmInfo &MAI) { @@ -43,7 +35,7 @@ static bool NameNeedsEscaping(StringRef Str, const MCAsmInfo &MAI) { // 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) @@ -52,59 +44,14 @@ static bool NameNeedsEscaping(StringRef Str, const MCAsmInfo &MAI) { return false; } -/// printMangledName - Print the specified string in mangled form if it uses -/// any unusual characters. -void MCSymbol::printMangledName(StringRef Str, raw_ostream &OS, - 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(OS, Str[0]); - Str = Str.substr(1); - } - - for (unsigned i = 0, e = Str.size(); i != e; ++i) { - if (!isAcceptableChar(Str[i])) - MangleLetter(OS, Str[i]); - else - OS << Str[i]; - } -} - -/// PrintMangledQuotedName - 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 PrintMangledQuotedName(raw_ostream &OS, StringRef Str) { - OS << '"'; - - for (unsigned i = 0, e = Str.size(); i != e; ++i) { - if (Str[i] == '"') - OS << "_QQ_"; - else if (Str[i] == '\n') - OS << "_NL_"; - else - OS << Str[i]; - } - OS << '"'; -} - - void MCSymbol::print(raw_ostream &OS, const MCAsmInfo *MAI) const { + // The name for this MCSymbol is required to be a valid target name. However, + // some targets support quoting names with funny characters. If the name + // contains a funny character, then print it quoted. if (MAI == 0 || !NameNeedsEscaping(getName(), *MAI)) { OS << getName(); return; } - - // On systems that do not allow quoted names, print with mangling. - if (!MAI->doesAllowQuotesInName()) - return printMangledName(getName(), OS, MAI); - - // If the string contains a double quote or newline, we still have to mangle - // it. - if (getName().find('"') != std::string::npos || - getName().find('\n') != std::string::npos) - return PrintMangledQuotedName(OS, getName()); OS << '"' << getName() << '"'; } diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index 7fd54ad3797..6a7643a79b6 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -352,10 +352,9 @@ char CWriter::ID = 0; 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 @@ std::string CWriter::GetValueName(const Value *Operand) { if (const GlobalValue *GV = dyn_cast(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 5579bfc5d9d..826f950c4a4 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 &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 &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 &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 @@ void Mangler::getNameWithPrefix(SmallVectorImpl &OutName, 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 @@ void Mangler::getNameWithPrefix(SmallVectorImpl &OutName, 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 39c90cd8f9b..93cb420d628 100644 --- a/lib/Target/TargetLoweringObjectFile.cpp +++ b/lib/Target/TargetLoweringObjectFile.cpp @@ -579,18 +579,11 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, // 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;