clang API Documentation
00001 //===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // Implements generic name mangling support for blocks and Objective-C. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 #include "clang/AST/Attr.h" 00014 #include "clang/AST/ASTContext.h" 00015 #include "clang/AST/Decl.h" 00016 #include "clang/AST/DeclCXX.h" 00017 #include "clang/AST/DeclObjC.h" 00018 #include "clang/AST/DeclTemplate.h" 00019 #include "clang/AST/ExprCXX.h" 00020 #include "clang/AST/Mangle.h" 00021 #include "clang/Basic/ABI.h" 00022 #include "clang/Basic/SourceManager.h" 00023 #include "clang/Basic/TargetInfo.h" 00024 #include "llvm/ADT/StringExtras.h" 00025 #include "llvm/Support/ErrorHandling.h" 00026 #include "llvm/Support/raw_ostream.h" 00027 00028 #define MANGLE_CHECKER 0 00029 00030 #if MANGLE_CHECKER 00031 #include <cxxabi.h> 00032 #endif 00033 00034 using namespace clang; 00035 00036 // FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves 00037 // much to be desired. Come up with a better mangling scheme. 00038 00039 static void mangleFunctionBlock(MangleContext &Context, 00040 StringRef Outer, 00041 const BlockDecl *BD, 00042 raw_ostream &Out) { 00043 unsigned discriminator = Context.getBlockId(BD, true); 00044 if (discriminator == 0) 00045 Out << "__" << Outer << "_block_invoke"; 00046 else 00047 Out << "__" << Outer << "_block_invoke_" << discriminator+1; 00048 } 00049 00050 void MangleContext::anchor() { } 00051 00052 enum CCMangling { 00053 CCM_Other, 00054 CCM_Fast, 00055 CCM_Vector, 00056 CCM_Std 00057 }; 00058 00059 static bool isExternC(const NamedDecl *ND) { 00060 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) 00061 return FD->isExternC(); 00062 return cast<VarDecl>(ND)->isExternC(); 00063 } 00064 00065 static CCMangling getCallingConvMangling(const ASTContext &Context, 00066 const NamedDecl *ND) { 00067 const TargetInfo &TI = Context.getTargetInfo(); 00068 const llvm::Triple &Triple = TI.getTriple(); 00069 if (!Triple.isOSWindows() || 00070 !(Triple.getArch() == llvm::Triple::x86 || 00071 Triple.getArch() == llvm::Triple::x86_64)) 00072 return CCM_Other; 00073 00074 if (Context.getLangOpts().CPlusPlus && !isExternC(ND) && 00075 TI.getCXXABI() == TargetCXXABI::Microsoft) 00076 return CCM_Other; 00077 00078 const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND); 00079 if (!FD) 00080 return CCM_Other; 00081 QualType T = FD->getType(); 00082 00083 const FunctionType *FT = T->castAs<FunctionType>(); 00084 00085 CallingConv CC = FT->getCallConv(); 00086 switch (CC) { 00087 default: 00088 return CCM_Other; 00089 case CC_X86FastCall: 00090 return CCM_Fast; 00091 case CC_X86StdCall: 00092 return CCM_Std; 00093 case CC_X86VectorCall: 00094 return CCM_Vector; 00095 } 00096 } 00097 00098 bool MangleContext::shouldMangleDeclName(const NamedDecl *D) { 00099 const ASTContext &ASTContext = getASTContext(); 00100 00101 CCMangling CC = getCallingConvMangling(ASTContext, D); 00102 if (CC != CCM_Other) 00103 return true; 00104 00105 // In C, functions with no attributes never need to be mangled. Fastpath them. 00106 if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs()) 00107 return false; 00108 00109 // Any decl can be declared with __asm("foo") on it, and this takes precedence 00110 // over all other naming in the .o file. 00111 if (D->hasAttr<AsmLabelAttr>()) 00112 return true; 00113 00114 return shouldMangleCXXName(D); 00115 } 00116 00117 void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) { 00118 // Any decl can be declared with __asm("foo") on it, and this takes precedence 00119 // over all other naming in the .o file. 00120 if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) { 00121 // If we have an asm name, then we use it as the mangling. 00122 00123 // Adding the prefix can cause problems when one file has a "foo" and 00124 // another has a "\01foo". That is known to happen on ELF with the 00125 // tricks normally used for producing aliases (PR9177). Fortunately the 00126 // llvm mangler on ELF is a nop, so we can just avoid adding the \01 00127 // marker. We also avoid adding the marker if this is an alias for an 00128 // LLVM intrinsic. 00129 StringRef UserLabelPrefix = 00130 getASTContext().getTargetInfo().getUserLabelPrefix(); 00131 if (!UserLabelPrefix.empty() && !ALA->getLabel().startswith("llvm.")) 00132 Out << '\01'; // LLVM IR Marker for __asm("foo") 00133 00134 Out << ALA->getLabel(); 00135 return; 00136 } 00137 00138 const ASTContext &ASTContext = getASTContext(); 00139 CCMangling CC = getCallingConvMangling(ASTContext, D); 00140 bool MCXX = shouldMangleCXXName(D); 00141 const TargetInfo &TI = Context.getTargetInfo(); 00142 if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) { 00143 if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) 00144 mangleObjCMethodName(OMD, Out); 00145 else 00146 mangleCXXName(D, Out); 00147 return; 00148 } 00149 00150 Out << '\01'; 00151 if (CC == CCM_Std) 00152 Out << '_'; 00153 else if (CC == CCM_Fast) 00154 Out << '@'; 00155 00156 if (!MCXX) 00157 Out << D->getIdentifier()->getName(); 00158 else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) 00159 mangleObjCMethodName(OMD, Out); 00160 else 00161 mangleCXXName(D, Out); 00162 00163 const FunctionDecl *FD = cast<FunctionDecl>(D); 00164 const FunctionType *FT = FD->getType()->castAs<FunctionType>(); 00165 const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT); 00166 if (CC == CCM_Vector) 00167 Out << '@'; 00168 Out << '@'; 00169 if (!Proto) { 00170 Out << '0'; 00171 return; 00172 } 00173 assert(!Proto->isVariadic()); 00174 unsigned ArgWords = 0; 00175 if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) 00176 if (!MD->isStatic()) 00177 ++ArgWords; 00178 for (const auto &AT : Proto->param_types()) 00179 // Size should be aligned to pointer size. 00180 ArgWords += llvm::RoundUpToAlignment(ASTContext.getTypeSize(AT), 00181 TI.getPointerWidth(0)) / 00182 TI.getPointerWidth(0); 00183 Out << ((TI.getPointerWidth(0) / 8) * ArgWords); 00184 } 00185 00186 void MangleContext::mangleGlobalBlock(const BlockDecl *BD, 00187 const NamedDecl *ID, 00188 raw_ostream &Out) { 00189 unsigned discriminator = getBlockId(BD, false); 00190 if (ID) { 00191 if (shouldMangleDeclName(ID)) 00192 mangleName(ID, Out); 00193 else { 00194 Out << ID->getIdentifier()->getName(); 00195 } 00196 } 00197 if (discriminator == 0) 00198 Out << "_block_invoke"; 00199 else 00200 Out << "_block_invoke_" << discriminator+1; 00201 } 00202 00203 void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD, 00204 CXXCtorType CT, const BlockDecl *BD, 00205 raw_ostream &ResStream) { 00206 SmallString<64> Buffer; 00207 llvm::raw_svector_ostream Out(Buffer); 00208 mangleCXXCtor(CD, CT, Out); 00209 Out.flush(); 00210 mangleFunctionBlock(*this, Buffer, BD, ResStream); 00211 } 00212 00213 void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD, 00214 CXXDtorType DT, const BlockDecl *BD, 00215 raw_ostream &ResStream) { 00216 SmallString<64> Buffer; 00217 llvm::raw_svector_ostream Out(Buffer); 00218 mangleCXXDtor(DD, DT, Out); 00219 Out.flush(); 00220 mangleFunctionBlock(*this, Buffer, BD, ResStream); 00221 } 00222 00223 void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD, 00224 raw_ostream &Out) { 00225 assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC)); 00226 00227 SmallString<64> Buffer; 00228 llvm::raw_svector_ostream Stream(Buffer); 00229 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) { 00230 mangleObjCMethodName(Method, Stream); 00231 } else { 00232 assert((isa<NamedDecl>(DC) || isa<BlockDecl>(DC)) && 00233 "expected a NamedDecl or BlockDecl"); 00234 if (isa<BlockDecl>(DC)) 00235 for (; DC && isa<BlockDecl>(DC); DC = DC->getParent()) 00236 (void) getBlockId(cast<BlockDecl>(DC), true); 00237 assert((isa<TranslationUnitDecl>(DC) || isa<NamedDecl>(DC)) && 00238 "expected a TranslationUnitDecl or a NamedDecl"); 00239 if (auto ND = dyn_cast<NamedDecl>(DC)) { 00240 if (!shouldMangleDeclName(ND) && ND->getIdentifier()) 00241 Stream << ND->getIdentifier()->getName(); 00242 else { 00243 // FIXME: We were doing a mangleUnqualifiedName() before, but that's 00244 // a private member of a class that will soon itself be private to the 00245 // Itanium C++ ABI object. What should we do now? Right now, I'm just 00246 // calling the mangleName() method on the MangleContext; is there a 00247 // better way? 00248 mangleName(ND, Stream); 00249 } 00250 } 00251 } 00252 Stream.flush(); 00253 mangleFunctionBlock(*this, Buffer, BD, Out); 00254 } 00255 00256 void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD, 00257 raw_ostream &Out) { 00258 SmallString<64> Name; 00259 llvm::raw_svector_ostream OS(Name); 00260 00261 const ObjCContainerDecl *CD = 00262 dyn_cast<ObjCContainerDecl>(MD->getDeclContext()); 00263 assert (CD && "Missing container decl in GetNameForMethod"); 00264 OS << (MD->isInstanceMethod() ? '-' : '+') << '[' << CD->getName(); 00265 if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD)) 00266 OS << '(' << *CID << ')'; 00267 OS << ' '; 00268 MD->getSelector().print(OS); 00269 OS << ']'; 00270 00271 Out << OS.str().size() << OS.str(); 00272 }