1202878Srdivacky//===-- Mangler.cpp - Self-contained c/asm llvm name mangler --------------===//
2202878Srdivacky//
3202878Srdivacky//                     The LLVM Compiler Infrastructure
4202878Srdivacky//
5202878Srdivacky// This file is distributed under the University of Illinois Open Source
6202878Srdivacky// License. See LICENSE.TXT for details.
7202878Srdivacky//
8202878Srdivacky//===----------------------------------------------------------------------===//
9202878Srdivacky//
10202878Srdivacky// Unified name mangler for assembly backends.
11202878Srdivacky//
12202878Srdivacky//===----------------------------------------------------------------------===//
13202878Srdivacky
14202878Srdivacky#include "llvm/Target/Mangler.h"
15249423Sdim#include "llvm/ADT/SmallString.h"
16249423Sdim#include "llvm/ADT/Twine.h"
17249423Sdim#include "llvm/IR/DataLayout.h"
18249423Sdim#include "llvm/IR/DerivedTypes.h"
19249423Sdim#include "llvm/IR/Function.h"
20202878Srdivacky#include "llvm/MC/MCAsmInfo.h"
21205218Srdivacky#include "llvm/MC/MCContext.h"
22205218Srdivacky#include "llvm/Support/raw_ostream.h"
23202878Srdivackyusing namespace llvm;
24202878Srdivacky
25234353Sdimstatic bool isAcceptableChar(char C, bool AllowPeriod, bool AllowUTF8) {
26202878Srdivacky  if ((C < 'a' || C > 'z') &&
27202878Srdivacky      (C < 'A' || C > 'Z') &&
28202878Srdivacky      (C < '0' || C > '9') &&
29207618Srdivacky      C != '_' && C != '$' && C != '@' &&
30234353Sdim      !(AllowPeriod && C == '.') &&
31234353Sdim      !(AllowUTF8 && (C & 0x80)))
32202878Srdivacky    return false;
33202878Srdivacky  return true;
34202878Srdivacky}
35202878Srdivacky
36202878Srdivackystatic char HexDigit(int V) {
37202878Srdivacky  return V < 10 ? V+'0' : V+'A'-10;
38202878Srdivacky}
39202878Srdivacky
40202878Srdivackystatic void MangleLetter(SmallVectorImpl<char> &OutName, unsigned char C) {
41202878Srdivacky  OutName.push_back('_');
42202878Srdivacky  OutName.push_back(HexDigit(C >> 4));
43202878Srdivacky  OutName.push_back(HexDigit(C & 15));
44202878Srdivacky  OutName.push_back('_');
45202878Srdivacky}
46202878Srdivacky
47243830Sdim/// NameNeedsEscaping - Return true if the identifier \p Str needs quotes
48202878Srdivacky/// for this assembler.
49202878Srdivackystatic bool NameNeedsEscaping(StringRef Str, const MCAsmInfo &MAI) {
50202878Srdivacky  assert(!Str.empty() && "Cannot create an empty MCSymbol");
51202878Srdivacky
52202878Srdivacky  // If the first character is a number and the target does not allow this, we
53202878Srdivacky  // need quotes.
54202878Srdivacky  if (!MAI.doesAllowNameToStartWithDigit() && Str[0] >= '0' && Str[0] <= '9')
55202878Srdivacky    return true;
56202878Srdivacky
57202878Srdivacky  // If any of the characters in the string is an unacceptable character, force
58202878Srdivacky  // quotes.
59207618Srdivacky  bool AllowPeriod = MAI.doesAllowPeriodsInName();
60234353Sdim  bool AllowUTF8 = MAI.doesAllowUTF8();
61202878Srdivacky  for (unsigned i = 0, e = Str.size(); i != e; ++i)
62234353Sdim    if (!isAcceptableChar(Str[i], AllowPeriod, AllowUTF8))
63202878Srdivacky      return true;
64202878Srdivacky  return false;
65202878Srdivacky}
66202878Srdivacky
67202878Srdivacky/// appendMangledName - Add the specified string in mangled form if it uses
68202878Srdivacky/// any unusual characters.
69202878Srdivackystatic void appendMangledName(SmallVectorImpl<char> &OutName, StringRef Str,
70205218Srdivacky                              const MCAsmInfo &MAI) {
71202878Srdivacky  // The first character is not allowed to be a number unless the target
72202878Srdivacky  // explicitly allows it.
73205218Srdivacky  if (!MAI.doesAllowNameToStartWithDigit() && Str[0] >= '0' && Str[0] <= '9') {
74202878Srdivacky    MangleLetter(OutName, Str[0]);
75202878Srdivacky    Str = Str.substr(1);
76202878Srdivacky  }
77207618Srdivacky
78207618Srdivacky  bool AllowPeriod = MAI.doesAllowPeriodsInName();
79234353Sdim  bool AllowUTF8 = MAI.doesAllowUTF8();
80202878Srdivacky  for (unsigned i = 0, e = Str.size(); i != e; ++i) {
81234353Sdim    if (!isAcceptableChar(Str[i], AllowPeriod, AllowUTF8))
82202878Srdivacky      MangleLetter(OutName, Str[i]);
83202878Srdivacky    else
84202878Srdivacky      OutName.push_back(Str[i]);
85202878Srdivacky  }
86202878Srdivacky}
87202878Srdivacky
88202878Srdivacky
89202878Srdivacky/// appendMangledQuotedName - On systems that support quoted symbols, we still
90202878Srdivacky/// have to escape some (obscure) characters like " and \n which would break the
91202878Srdivacky/// assembler's lexing.
92202878Srdivackystatic void appendMangledQuotedName(SmallVectorImpl<char> &OutName,
93202878Srdivacky                                   StringRef Str) {
94202878Srdivacky  for (unsigned i = 0, e = Str.size(); i != e; ++i) {
95202878Srdivacky    if (Str[i] == '"' || Str[i] == '\n')
96202878Srdivacky      MangleLetter(OutName, Str[i]);
97202878Srdivacky    else
98202878Srdivacky      OutName.push_back(Str[i]);
99202878Srdivacky  }
100202878Srdivacky}
101202878Srdivacky
102202878Srdivacky
103202878Srdivacky/// getNameWithPrefix - Fill OutName with the name of the appropriate prefix
104202878Srdivacky/// and the specified name as the global variable name.  GVName must not be
105202878Srdivacky/// empty.
106202878Srdivackyvoid Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
107202878Srdivacky                                const Twine &GVName, ManglerPrefixTy PrefixTy) {
108202878Srdivacky  SmallString<256> TmpData;
109202878Srdivacky  StringRef Name = GVName.toStringRef(TmpData);
110202878Srdivacky  assert(!Name.empty() && "getNameWithPrefix requires non-empty name");
111202878Srdivacky
112205218Srdivacky  const MCAsmInfo &MAI = Context.getAsmInfo();
113205218Srdivacky
114202878Srdivacky  // If the global name is not led with \1, add the appropriate prefixes.
115202878Srdivacky  if (Name[0] == '\1') {
116202878Srdivacky    Name = Name.substr(1);
117202878Srdivacky  } else {
118202878Srdivacky    if (PrefixTy == Mangler::Private) {
119202878Srdivacky      const char *Prefix = MAI.getPrivateGlobalPrefix();
120202878Srdivacky      OutName.append(Prefix, Prefix+strlen(Prefix));
121202878Srdivacky    } else if (PrefixTy == Mangler::LinkerPrivate) {
122202878Srdivacky      const char *Prefix = MAI.getLinkerPrivateGlobalPrefix();
123202878Srdivacky      OutName.append(Prefix, Prefix+strlen(Prefix));
124202878Srdivacky    }
125202878Srdivacky
126202878Srdivacky    const char *Prefix = MAI.getGlobalPrefix();
127202878Srdivacky    if (Prefix[0] == 0)
128202878Srdivacky      ; // Common noop, no prefix.
129202878Srdivacky    else if (Prefix[1] == 0)
130202878Srdivacky      OutName.push_back(Prefix[0]);  // Common, one character prefix.
131202878Srdivacky    else
132202878Srdivacky      OutName.append(Prefix, Prefix+strlen(Prefix)); // Arbitrary length prefix.
133202878Srdivacky  }
134202878Srdivacky
135202878Srdivacky  // If this is a simple string that doesn't need escaping, just append it.
136202878Srdivacky  if (!NameNeedsEscaping(Name, MAI) ||
137202878Srdivacky      // If quotes are supported, they can be used unless the string contains
138202878Srdivacky      // a quote or newline.
139202878Srdivacky      (MAI.doesAllowQuotesInName() &&
140202878Srdivacky       Name.find_first_of("\n\"") == StringRef::npos)) {
141202878Srdivacky    OutName.append(Name.begin(), Name.end());
142202878Srdivacky    return;
143202878Srdivacky  }
144202878Srdivacky
145202878Srdivacky  // On systems that do not allow quoted names, we need to mangle most
146202878Srdivacky  // strange characters.
147202878Srdivacky  if (!MAI.doesAllowQuotesInName())
148205218Srdivacky    return appendMangledName(OutName, Name, MAI);
149202878Srdivacky
150202878Srdivacky  // Okay, the system allows quoted strings.  We can quote most anything, the
151202878Srdivacky  // only characters that need escaping are " and \n.
152202878Srdivacky  assert(Name.find_first_of("\n\"") != StringRef::npos);
153202878Srdivacky  return appendMangledQuotedName(OutName, Name);
154202878Srdivacky}
155202878Srdivacky
156205218Srdivacky/// AddFastCallStdCallSuffix - Microsoft fastcall and stdcall functions require
157205218Srdivacky/// a suffix on their name indicating the number of words of arguments they
158205218Srdivacky/// take.
159205218Srdivackystatic void AddFastCallStdCallSuffix(SmallVectorImpl<char> &OutName,
160243830Sdim                                     const Function *F, const DataLayout &TD) {
161205218Srdivacky  // Calculate arguments size total.
162205218Srdivacky  unsigned ArgWords = 0;
163205218Srdivacky  for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
164205218Srdivacky       AI != AE; ++AI) {
165226633Sdim    Type *Ty = AI->getType();
166205218Srdivacky    // 'Dereference' type in case of byval parameter attribute
167205218Srdivacky    if (AI->hasByValAttr())
168205218Srdivacky      Ty = cast<PointerType>(Ty)->getElementType();
169205218Srdivacky    // Size should be aligned to DWORD boundary
170205218Srdivacky    ArgWords += ((TD.getTypeAllocSize(Ty) + 3)/4)*4;
171205218Srdivacky  }
172205218Srdivacky
173205218Srdivacky  raw_svector_ostream(OutName) << '@' << ArgWords;
174205218Srdivacky}
175202878Srdivacky
176205218Srdivacky
177202878Srdivacky/// getNameWithPrefix - Fill OutName with the name of the appropriate prefix
178202878Srdivacky/// and the specified global variable's name.  If the global variable doesn't
179202878Srdivacky/// have a name, this fills in a unique name for the global.
180202878Srdivackyvoid Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
181202878Srdivacky                                const GlobalValue *GV,
182202878Srdivacky                                bool isImplicitlyPrivate) {
183202878Srdivacky  ManglerPrefixTy PrefixTy = Mangler::Default;
184202878Srdivacky  if (GV->hasPrivateLinkage() || isImplicitlyPrivate)
185202878Srdivacky    PrefixTy = Mangler::Private;
186243830Sdim  else if (GV->hasLinkerPrivateLinkage() || GV->hasLinkerPrivateWeakLinkage())
187202878Srdivacky    PrefixTy = Mangler::LinkerPrivate;
188202878Srdivacky
189202878Srdivacky  // If this global has a name, handle it simply.
190205218Srdivacky  if (GV->hasName()) {
191251662Sdim    StringRef Name = GV->getName();
192251662Sdim    getNameWithPrefix(OutName, Name, PrefixTy);
193251662Sdim    // No need to do anything else if the global has the special "do not mangle"
194251662Sdim    // flag in the name.
195251662Sdim    if (Name[0] == 1)
196251662Sdim      return;
197205218Srdivacky  } else {
198205218Srdivacky    // Get the ID for the global, assigning a new one if we haven't got one
199205218Srdivacky    // already.
200205218Srdivacky    unsigned &ID = AnonGlobalIDs[GV];
201205218Srdivacky    if (ID == 0) ID = NextAnonGlobalID++;
202202878Srdivacky
203205218Srdivacky    // Must mangle the global into a unique ID.
204205218Srdivacky    getNameWithPrefix(OutName, "__unnamed_" + Twine(ID), PrefixTy);
205205218Srdivacky  }
206202878Srdivacky
207205218Srdivacky  // If we are supposed to add a microsoft-style suffix for stdcall/fastcall,
208205218Srdivacky  // add it.
209205218Srdivacky  if (Context.getAsmInfo().hasMicrosoftFastStdCallMangling()) {
210205218Srdivacky    if (const Function *F = dyn_cast<Function>(GV)) {
211205218Srdivacky      CallingConv::ID CC = F->getCallingConv();
212205218Srdivacky
213205218Srdivacky      // fastcall functions need to start with @.
214205218Srdivacky      // FIXME: This logic seems unlikely to be right.
215205218Srdivacky      if (CC == CallingConv::X86_FastCall) {
216205218Srdivacky        if (OutName[0] == '_')
217205218Srdivacky          OutName[0] = '@';
218205218Srdivacky        else
219205218Srdivacky          OutName.insert(OutName.begin(), '@');
220205218Srdivacky      }
221205218Srdivacky
222205218Srdivacky      // fastcall and stdcall functions usually need @42 at the end to specify
223205218Srdivacky      // the argument info.
224226633Sdim      FunctionType *FT = F->getFunctionType();
225205218Srdivacky      if ((CC == CallingConv::X86_FastCall || CC == CallingConv::X86_StdCall) &&
226205218Srdivacky          // "Pure" variadic functions do not receive @0 suffix.
227205218Srdivacky          (!FT->isVarArg() || FT->getNumParams() == 0 ||
228205218Srdivacky           (FT->getNumParams() == 1 && F->hasStructRetAttr())))
229205218Srdivacky        AddFastCallStdCallSuffix(OutName, F, TD);
230205218Srdivacky    }
231205218Srdivacky  }
232202878Srdivacky}
233202878Srdivacky
234205218Srdivacky/// getSymbol - Return the MCSymbol for the specified global value.  This
235205218Srdivacky/// symbol is the main label that is the address of the global.
236205218SrdivackyMCSymbol *Mangler::getSymbol(const GlobalValue *GV) {
237205218Srdivacky  SmallString<60> NameStr;
238205218Srdivacky  getNameWithPrefix(NameStr, GV, false);
239206083Srdivacky  return Context.GetOrCreateSymbol(NameStr.str());
240205218Srdivacky}
241205218Srdivacky
242205218Srdivacky
243