#include "llvm/IR/Mangler.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
const Twine &GVName, ManglerPrefixTy PrefixTy) {
SmallString<256> TmpData;
StringRef Name = GVName.toStringRef(TmpData);
assert(!Name.empty() && "getNameWithPrefix requires non-empty name");
if (Name[0] == '\1') {
Name = Name.substr(1);
} else {
if (PrefixTy == Mangler::Private) {
const char *Prefix = DL->getPrivateGlobalPrefix();
OutName.append(Prefix, Prefix+strlen(Prefix));
} else if (PrefixTy == Mangler::LinkerPrivate) {
const char *Prefix = DL->getLinkerPrivateGlobalPrefix();
OutName.append(Prefix, Prefix+strlen(Prefix));
}
char Prefix = DL->getGlobalPrefix();
if (Prefix != '\0')
OutName.push_back(Prefix);
}
OutName.append(Name.begin(), Name.end());
}
static void AddFastCallStdCallSuffix(SmallVectorImpl<char> &OutName,
const Function *F, const DataLayout &TD) {
unsigned ArgWords = 0;
for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
AI != AE; ++AI) {
Type *Ty = AI->getType();
if (AI->hasByValOrInAllocaAttr())
Ty = cast<PointerType>(Ty)->getElementType();
ArgWords += ((TD.getTypeAllocSize(Ty) + 3)/4)*4;
}
raw_svector_ostream(OutName) << '@' << ArgWords;
}
void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
const GlobalValue *GV,
bool CannotUsePrivateLabel) {
ManglerPrefixTy PrefixTy = Mangler::Default;
if (GV->hasPrivateLinkage()) {
if (CannotUsePrivateLabel)
PrefixTy = Mangler::LinkerPrivate;
else
PrefixTy = Mangler::Private;
} else if (GV->hasLinkerPrivateLinkage() ||
GV->hasLinkerPrivateWeakLinkage()) {
PrefixTy = Mangler::LinkerPrivate;
}
size_t NameBegin = OutName.size();
if (GV->hasName()) {
StringRef Name = GV->getName();
getNameWithPrefix(OutName, Name, PrefixTy);
if (Name[0] == 1)
return;
} else {
unsigned &ID = AnonGlobalIDs[GV];
if (ID == 0) ID = NextAnonGlobalID++;
getNameWithPrefix(OutName, "__unnamed_" + Twine(ID), PrefixTy);
}
if (DL->hasMicrosoftFastStdCallMangling()) {
if (const Function *F = dyn_cast<Function>(GV)) {
CallingConv::ID CC = F->getCallingConv();
if (CC == CallingConv::X86_FastCall) {
assert(OutName[NameBegin] == '_' && DL->getGlobalPrefix() == '_');
OutName[NameBegin] = '@';
}
FunctionType *FT = F->getFunctionType();
if ((CC == CallingConv::X86_FastCall || CC == CallingConv::X86_StdCall) &&
(!FT->isVarArg() || FT->getNumParams() == 0 ||
(FT->getNumParams() == 1 && F->hasStructRetAttr())))
AddFastCallStdCallSuffix(OutName, F, *DL);
}
}
}