summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2010-03-21 10:50:08 +0000
committerrdivacky <rdivacky@FreeBSD.org>2010-03-21 10:50:08 +0000
commit1e255aab650a7fa2047fd953cae65b12215280af (patch)
tree508d4388db78f87d35bf26a0400b4b03bc4c1f13 /lib/CodeGen
parent1033b7c1e32962948b01a25145829f17bc70a8de (diff)
downloadFreeBSD-src-1e255aab650a7fa2047fd953cae65b12215280af.zip
FreeBSD-src-1e255aab650a7fa2047fd953cae65b12215280af.tar.gz
Update clang to r99115.
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CGBuiltin.cpp76
-rw-r--r--lib/CodeGen/CGCXX.cpp55
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp20
-rw-r--r--lib/CodeGen/CGDecl.cpp15
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp48
-rw-r--r--lib/CodeGen/CGException.cpp34
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp2
-rw-r--r--lib/CodeGen/CGVtable.cpp108
-rw-r--r--lib/CodeGen/CodeGenFunction.h6
-rw-r--r--lib/CodeGen/CodeGenModule.cpp159
-rw-r--r--lib/CodeGen/CodeGenModule.h72
-rw-r--r--lib/CodeGen/Mangle.cpp45
-rw-r--r--lib/CodeGen/Mangle.h33
13 files changed, 417 insertions, 256 deletions
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 706e441..419ed73 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -25,17 +25,47 @@ using namespace clang;
using namespace CodeGen;
using namespace llvm;
+static void EmitMemoryBarrier(CodeGenFunction &CGF,
+ bool LoadLoad, bool LoadStore,
+ bool StoreLoad, bool StoreStore,
+ bool Device) {
+ Value *True = llvm::ConstantInt::getTrue(CGF.getLLVMContext());
+ Value *False = llvm::ConstantInt::getFalse(CGF.getLLVMContext());
+ Value *C[5] = { LoadLoad ? True : False,
+ LoadStore ? True : False,
+ StoreLoad ? True : False,
+ StoreStore ? True : False,
+ Device ? True : False };
+ CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(Intrinsic::memory_barrier),
+ C, C + 5);
+}
+
+// The atomic builtins are also full memory barriers. This is a utility for
+// wrapping a call to the builtins with memory barriers.
+static Value *EmitCallWithBarrier(CodeGenFunction &CGF, Value *Fn,
+ Value **ArgBegin, Value **ArgEnd) {
+ // FIXME: We need a target hook for whether this applies to device memory or
+ // not.
+ bool Device = true;
+
+ // Create barriers both before and after the call.
+ EmitMemoryBarrier(CGF, true, true, true, true, Device);
+ Value *Result = CGF.Builder.CreateCall(Fn, ArgBegin, ArgEnd);
+ EmitMemoryBarrier(CGF, true, true, true, true, Device);
+ return Result;
+}
+
/// Utility to insert an atomic instruction based on Instrinsic::ID
/// and the expression node.
-static RValue EmitBinaryAtomic(CodeGenFunction& CGF,
+static RValue EmitBinaryAtomic(CodeGenFunction &CGF,
Intrinsic::ID Id, const CallExpr *E) {
+ Value *Args[2] = { CGF.EmitScalarExpr(E->getArg(0)),
+ CGF.EmitScalarExpr(E->getArg(1)) };
const llvm::Type *ResType[2];
ResType[0] = CGF.ConvertType(E->getType());
ResType[1] = CGF.ConvertType(E->getArg(0)->getType());
Value *AtomF = CGF.CGM.getIntrinsic(Id, ResType, 2);
- return RValue::get(CGF.Builder.CreateCall2(AtomF,
- CGF.EmitScalarExpr(E->getArg(0)),
- CGF.EmitScalarExpr(E->getArg(1))));
+ return RValue::get(EmitCallWithBarrier(CGF, AtomF, Args, Args + 2));
}
/// Utility to insert an atomic instruction based Instrinsic::ID and
@@ -48,15 +78,14 @@ static RValue EmitBinaryAtomicPost(CodeGenFunction& CGF,
ResType[0] = CGF.ConvertType(E->getType());
ResType[1] = CGF.ConvertType(E->getArg(0)->getType());
Value *AtomF = CGF.CGM.getIntrinsic(Id, ResType, 2);
- Value *Ptr = CGF.EmitScalarExpr(E->getArg(0));
- Value *Operand = CGF.EmitScalarExpr(E->getArg(1));
- Value *Result = CGF.Builder.CreateCall2(AtomF, Ptr, Operand);
+ Value *Args[2] = { CGF.EmitScalarExpr(E->getArg(0)),
+ CGF.EmitScalarExpr(E->getArg(1)) };
+ Value *Result = EmitCallWithBarrier(CGF, AtomF, Args, Args + 2);
if (Id == Intrinsic::atomic_load_nand)
Result = CGF.Builder.CreateNot(Result);
-
- return RValue::get(CGF.Builder.CreateBinOp(Op, Result, Operand));
+ return RValue::get(CGF.Builder.CreateBinOp(Op, Result, Args[1]));
}
static llvm::ConstantInt *getInt32(llvm::LLVMContext &Context, int32_t Value) {
@@ -585,33 +614,31 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__sync_val_compare_and_swap_2:
case Builtin::BI__sync_val_compare_and_swap_4:
case Builtin::BI__sync_val_compare_and_swap_8:
- case Builtin::BI__sync_val_compare_and_swap_16:
- {
+ case Builtin::BI__sync_val_compare_and_swap_16: {
const llvm::Type *ResType[2];
ResType[0]= ConvertType(E->getType());
ResType[1] = ConvertType(E->getArg(0)->getType());
Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap, ResType, 2);
- return RValue::get(Builder.CreateCall3(AtomF,
- EmitScalarExpr(E->getArg(0)),
- EmitScalarExpr(E->getArg(1)),
- EmitScalarExpr(E->getArg(2))));
+ Value *Args[3] = { EmitScalarExpr(E->getArg(0)),
+ EmitScalarExpr(E->getArg(1)),
+ EmitScalarExpr(E->getArg(2)) };
+ return RValue::get(EmitCallWithBarrier(*this, AtomF, Args, Args + 3));
}
case Builtin::BI__sync_bool_compare_and_swap_1:
case Builtin::BI__sync_bool_compare_and_swap_2:
case Builtin::BI__sync_bool_compare_and_swap_4:
case Builtin::BI__sync_bool_compare_and_swap_8:
- case Builtin::BI__sync_bool_compare_and_swap_16:
- {
+ case Builtin::BI__sync_bool_compare_and_swap_16: {
const llvm::Type *ResType[2];
ResType[0]= ConvertType(E->getArg(1)->getType());
ResType[1] = llvm::PointerType::getUnqual(ResType[0]);
Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap, ResType, 2);
Value *OldVal = EmitScalarExpr(E->getArg(1));
- Value *PrevVal = Builder.CreateCall3(AtomF,
- EmitScalarExpr(E->getArg(0)),
- OldVal,
- EmitScalarExpr(E->getArg(2)));
+ Value *Args[3] = { EmitScalarExpr(E->getArg(0)),
+ OldVal,
+ EmitScalarExpr(E->getArg(2)) };
+ Value *PrevVal = EmitCallWithBarrier(*this, AtomF, Args, Args + 3);
Value *Result = Builder.CreateICmpEQ(PrevVal, OldVal);
// zext bool to int.
return RValue::get(Builder.CreateZExt(Result, ConvertType(E->getType())));
@@ -623,6 +650,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__sync_lock_test_and_set_8:
case Builtin::BI__sync_lock_test_and_set_16:
return EmitBinaryAtomic(*this, Intrinsic::atomic_swap, E);
+
case Builtin::BI__sync_lock_release_1:
case Builtin::BI__sync_lock_release_2:
case Builtin::BI__sync_lock_release_4:
@@ -638,10 +666,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
}
case Builtin::BI__sync_synchronize: {
- Value *C[5];
- C[0] = C[1] = C[2] = C[3] = llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), 1);
- C[4] = llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), 0);
- Builder.CreateCall(CGM.getIntrinsic(Intrinsic::memory_barrier), C, C + 5);
+ // We assume like gcc appears to, that this only applies to cached memory.
+ EmitMemoryBarrier(*this, true, true, true, true, false);
return RValue::get(0);
}
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 7752cf7..b88001c 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -165,19 +165,21 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
new llvm::GlobalAlias(AliasType, Linkage, "", Aliasee, &getModule());
// Switch any previous uses to the alias.
- const char *MangledName = getMangledName(AliasDecl);
- llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
+ MangleBuffer MangledName;
+ getMangledName(MangledName, AliasDecl);
+ llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (Entry) {
assert(Entry->isDeclaration() && "definition already exists for alias");
assert(Entry->getType() == AliasType &&
"declaration exists with different type");
+ Alias->takeName(Entry);
Entry->replaceAllUsesWith(Alias);
Entry->eraseFromParent();
+ } else {
+ Alias->setName(MangledName.getString());
}
- Entry = Alias;
// Finally, set up the alias with its proper name and attributes.
- Alias->setName(MangledName);
SetCommonAttributes(AliasDecl.getDecl(), Alias);
return false;
@@ -214,8 +216,9 @@ void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D,
llvm::GlobalValue *
CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
CXXCtorType Type) {
- const char *Name = getMangledCXXCtorName(D, Type);
- if (llvm::GlobalValue *V = GlobalDeclMap[Name])
+ MangleBuffer Name;
+ getMangledCXXCtorName(Name, D, Type);
+ if (llvm::GlobalValue *V = GetGlobalValue(Name))
return V;
const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>();
@@ -226,13 +229,10 @@ CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type)));
}
-const char *CodeGenModule::getMangledCXXCtorName(const CXXConstructorDecl *D,
- CXXCtorType Type) {
- llvm::SmallString<256> Name;
- getMangleContext().mangleCXXCtor(D, Type, Name);
-
- Name += '\0';
- return UniqueMangledName(Name.begin(), Name.end());
+void CodeGenModule::getMangledCXXCtorName(MangleBuffer &Name,
+ const CXXConstructorDecl *D,
+ CXXCtorType Type) {
+ getMangleContext().mangleCXXCtor(D, Type, Name.getBuffer());
}
void CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) {
@@ -279,8 +279,9 @@ void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D,
llvm::GlobalValue *
CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
CXXDtorType Type) {
- const char *Name = getMangledCXXDtorName(D, Type);
- if (llvm::GlobalValue *V = GlobalDeclMap[Name])
+ MangleBuffer Name;
+ getMangledCXXDtorName(Name, D, Type);
+ if (llvm::GlobalValue *V = GetGlobalValue(Name))
return V;
const llvm::FunctionType *FTy =
@@ -290,13 +291,10 @@ CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type)));
}
-const char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D,
- CXXDtorType Type) {
- llvm::SmallString<256> Name;
- getMangleContext().mangleCXXDtor(D, Type, Name);
-
- Name += '\0';
- return UniqueMangledName(Name.begin(), Name.end());
+void CodeGenModule::getMangledCXXDtorName(MangleBuffer &Name,
+ const CXXDestructorDecl *D,
+ CXXDtorType Type) {
+ getMangleContext().mangleCXXDtor(D, Type, Name.getBuffer());
}
llvm::Constant *
@@ -470,12 +468,10 @@ CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
OutName);
else
getMangleContext().mangleThunk(MD, ThisAdjustment, OutName);
- OutName += '\0';
- const char* Name = UniqueMangledName(OutName.begin(), OutName.end());
// Get function for mangled name
const llvm::Type *Ty = getTypes().GetFunctionTypeForVtable(MD);
- return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl());
+ return GetOrCreateLLVMFunction(OutName, Ty, GlobalDecl());
}
llvm::Constant *
@@ -484,10 +480,8 @@ CodeGenModule::GetAddrOfCovariantThunk(GlobalDecl GD,
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
// Compute mangled name
- llvm::SmallString<256> OutName;
- getMangleContext().mangleCovariantThunk(MD, Adjustment, OutName);
- OutName += '\0';
- const char* Name = UniqueMangledName(OutName.begin(), OutName.end());
+ llvm::SmallString<256> Name;
+ getMangleContext().mangleCovariantThunk(MD, Adjustment, Name);
// Get function for mangled name
const llvm::Type *Ty = getTypes().GetFunctionTypeForVtable(MD);
@@ -528,9 +522,6 @@ void CodeGenModule::BuildThunksForVirtual(GlobalDecl GD) {
llvm::Constant *SubExpr =
cast<llvm::ConstantExpr>(FnConst)->getOperand(0);
llvm::Function *OldFn = cast<llvm::Function>(SubExpr);
- std::string Name = OldFn->getNameStr();
- GlobalDeclMap.erase(UniqueMangledName(Name.data(),
- Name.data() + Name.size() + 1));
llvm::Constant *NewFnConst;
if (!ReturnAdjustment.isEmpty())
NewFnConst = GetAddrOfCovariantThunk(GD, CoAdj);
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 60aa4e7..ad97d08 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -104,12 +104,20 @@ llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
void CGDebugInfo::CreateCompileUnit() {
// Get absolute path name.
+ SourceManager &SM = CGM.getContext().getSourceManager();
std::string MainFileName = CGM.getCodeGenOpts().MainFileName;
if (MainFileName.empty())
MainFileName = "<unknown>";
+
llvm::sys::Path AbsFileName(MainFileName);
AbsFileName.makeAbsolute();
+ std::string MainFileDir;
+ if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID()))
+ MainFileDir = MainFile->getDir()->getName();
+ else
+ MainFileDir = AbsFileName.getDirname();
+
unsigned LangTag;
const LangOptions &LO = CGM.getLangOptions();
if (LO.CPlusPlus) {
@@ -138,7 +146,7 @@ void CGDebugInfo::CreateCompileUnit() {
// Create new compile unit.
TheCU = DebugFactory.CreateCompileUnit(
- LangTag, AbsFileName.getLast(), AbsFileName.getDirname(), Producer, true,
+ LangTag, AbsFileName.getLast(), MainFileDir, Producer, true,
LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers);
}
@@ -561,13 +569,13 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method);
llvm::StringRef MethodName = getFunctionName(Method);
- llvm::StringRef MethodLinkageName;
llvm::DIType MethodTy = getOrCreateMethodType(Method, Unit);
// Since a single ctor/dtor corresponds to multiple functions, it doesn't
// make sense to give a single ctor/dtor a linkage name.
+ MangleBuffer MethodLinkageName;
if (!IsCtorOrDtor)
- MethodLinkageName = CGM.getMangledName(Method);
+ CGM.getMangledName(MethodLinkageName, Method);
SourceManager &SM = CGM.getContext().getSourceManager();
@@ -1299,7 +1307,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
CGBuilderTy &Builder) {
llvm::StringRef Name;
- llvm::StringRef LinkageName;
+ MangleBuffer LinkageName;
const Decl *D = GD.getDecl();
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
@@ -1318,11 +1326,11 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
if (!Name.empty() && Name[0] == '\01')
Name = Name.substr(1);
// Use mangled name as linkage name for c/c++ functions.
- LinkageName = CGM.getMangledName(GD);
+ CGM.getMangledName(LinkageName, GD);
} else {
// Use llvm function name as linkage name.
Name = Fn->getName();
- LinkageName = Name;
+ LinkageName.setString(Name);
if (!Name.empty() && Name[0] == '\01')
Name = Name.substr(1);
}
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 1dc083f..4eb95af 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -103,13 +103,18 @@ void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) {
static std::string GetStaticDeclName(CodeGenFunction &CGF, const VarDecl &D,
const char *Separator) {
CodeGenModule &CGM = CGF.CGM;
- if (CGF.getContext().getLangOptions().CPlusPlus)
- return CGM.getMangledName(&D);
+ if (CGF.getContext().getLangOptions().CPlusPlus) {
+ MangleBuffer Name;
+ CGM.getMangledName(Name, &D);
+ return Name.getString().str();
+ }
std::string ContextName;
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CGF.CurFuncDecl))
- ContextName = CGM.getMangledName(FD);
- else if (isa<ObjCMethodDecl>(CGF.CurFuncDecl))
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CGF.CurFuncDecl)) {
+ MangleBuffer Name;
+ CGM.getMangledName(Name, FD);
+ ContextName = Name.getString().str();
+ } else if (isa<ObjCMethodDecl>(CGF.CurFuncDecl))
ContextName = CGF.CurFn->getName();
else
// FIXME: What about in a block??
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index 0de3b0b..40c18ca 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
+#include "clang/CodeGen/CodeGenOptions.h"
using namespace clang;
using namespace CodeGen;
@@ -64,7 +65,7 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
DeclPtr = llvm::Constant::getNullValue(Int8PtrTy);
} else
- DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);
+ DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);
CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
}
@@ -92,6 +93,12 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
void
CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
llvm::Constant *DeclPtr) {
+ // Generate a global destructor entry if not using __cxa_atexit.
+ if (!CGM.getCodeGenOpts().CXAAtExit) {
+ CGM.AddCXXDtorEntry(DtorFn, DeclPtr);
+ return;
+ }
+
const llvm::Type *Int8PtrTy =
llvm::Type::getInt8Ty(VMContext)->getPointerTo();
@@ -150,10 +157,9 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
false);
// Create our global initialization function.
- // FIXME: Should this be tweakable by targets?
llvm::Function *Fn =
llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
- "__cxx_global_initialization", &TheModule);
+ "_GLOBAL__I_a", &TheModule);
CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
&CXXGlobalInits[0],
@@ -161,6 +167,28 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
AddGlobalCtor(Fn);
}
+void CodeGenModule::AddCXXDtorEntry(llvm::Constant *DtorFn,
+ llvm::Constant *Object) {
+ CXXGlobalDtors.push_back(std::make_pair(DtorFn, Object));
+}
+
+void CodeGenModule::EmitCXXGlobalDtorFunc() {
+ if (CXXGlobalDtors.empty())
+ return;
+
+ const llvm::FunctionType *FTy
+ = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
+ false);
+
+ // Create our global destructor function.
+ llvm::Function *Fn =
+ llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
+ "_GLOBAL__D_a", &TheModule);
+
+ CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors);
+ AddGlobalDtor(Fn);
+}
+
void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
const VarDecl *D) {
StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
@@ -184,6 +212,20 @@ void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
FinishFunction();
}
+void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn,
+ const std::vector<std::pair<llvm::Constant*, llvm::Constant*> >
+ &DtorsAndObjects) {
+ StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(),
+ SourceLocation());
+
+ // Emit the dtors, in reverse order from construction.
+ for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i)
+ Builder.CreateCall(DtorsAndObjects[e - i - 1].first,
+ DtorsAndObjects[e - i - 1].second);
+
+ FinishFunction();
+}
+
static llvm::Constant *getGuardAcquireFn(CodeGenFunction &CGF) {
// int __cxa_guard_acquire(__int64_t *guard_object);
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index 142cb81..1e15066 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -486,8 +486,6 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S,
llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
llvm::Value *RethrowPtr = CreateTempAlloca(Exc->getType(), "_rethrow");
- llvm::SmallVector<llvm::Value*, 8> Args;
- Args.clear();
SelectorArgs.push_back(Exc);
SelectorArgs.push_back(Personality);
@@ -584,12 +582,11 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S,
llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
// We are required to emit this call to satisfy LLVM, even
// though we don't use the result.
- Args.clear();
- Args.push_back(Exc);
- Args.push_back(Personality);
- Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
- 0));
- Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
+ llvm::Value *Args[] = {
+ Exc, Personality,
+ llvm::ConstantInt::getNullValue(llvm::Type::getInt32Ty(VMContext))
+ };
+ Builder.CreateCall(llvm_eh_selector, &Args[0], llvm::array_endof(Args));
Builder.CreateStore(Exc, RethrowPtr);
EmitBranchThroughCleanup(FinallyRethrow);
@@ -600,7 +597,7 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S,
llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
Builder.CreateInvoke(getEndCatchFn(*this),
Cont, TerminateHandler,
- Args.begin(), Args.begin());
+ &Args[0], &Args[0]);
EmitBlock(Cont);
if (Info.SwitchBlock)
EmitBlock(Info.SwitchBlock);
@@ -677,12 +674,8 @@ CodeGenFunction::EHCleanupBlock::~EHCleanupBlock() {
// C string type. Used in lots of places.
PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty);
- llvm::SmallVector<llvm::Value*, 8> Args;
- Args.clear();
- Args.push_back(Exc);
- Args.push_back(Personality);
- Args.push_back(Null);
- CGF.Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
+ llvm::Value *Args[] = { Exc, Personality, Null };
+ CGF.Builder.CreateCall(llvm_eh_selector, &Args[0], llvm::array_endof(Args));
CGF.EmitBlock(CleanupEntryBB);
@@ -731,12 +724,11 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
// We are required to emit this call to satisfy LLVM, even
// though we don't use the result.
- llvm::SmallVector<llvm::Value*, 8> Args;
- Args.push_back(Exc);
- Args.push_back(Personality);
- Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
- 1));
- Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
+ llvm::Value *Args[] = {
+ Exc, Personality,
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)
+ };
+ Builder.CreateCall(llvm_eh_selector, &Args[0], llvm::array_endof(Args));
llvm::CallInst *TerminateCall =
Builder.CreateCall(getTerminateFn(*this));
TerminateCall->setDoesNotReturn();
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index 2436357..119819b 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -1634,7 +1634,7 @@ llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD,
const ObjCCategoryImplDecl *OCD =
dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext());
std::string CategoryName = OCD ? OCD->getNameAsString() : "";
- std::string ClassName = OMD->getClassInterface()->getNameAsString();
+ std::string ClassName = CD->getName();
std::string MethodName = OMD->getSelector().getAsString();
bool isClassMethod = !OMD->isInstanceMethod();
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index 9bcf986..df30f47 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -19,6 +19,7 @@
#include "llvm/ADT/SetVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Format.h"
+#include <algorithm>
#include <cstdio>
using namespace clang;
@@ -1147,6 +1148,12 @@ private:
ReturnAdjustment() : NonVirtual(0), VBaseOffsetOffset(0) { }
bool isEmpty() const { return !NonVirtual && !VBaseOffsetOffset; }
+
+ friend bool operator==(const ReturnAdjustment &LHS,
+ const ReturnAdjustment &RHS) {
+ return LHS.NonVirtual == RHS.NonVirtual &&
+ LHS.VBaseOffsetOffset == RHS.VBaseOffsetOffset;
+ }
};
/// MethodInfo - Contains information about a method in a vtable.
@@ -1191,6 +1198,12 @@ private:
ThisAdjustment() : NonVirtual(0), VCallOffsetOffset(0) { }
bool isEmpty() const { return !NonVirtual && !VCallOffsetOffset; }
+
+ friend bool operator==(const ThisAdjustment &LHS,
+ const ThisAdjustment &RHS) {
+ return LHS.NonVirtual == RHS.NonVirtual &&
+ LHS.VCallOffsetOffset == RHS.VCallOffsetOffset;
+ }
};
/// ThunkInfo - The 'this' pointer adjustment as well as an optional return
@@ -1206,8 +1219,12 @@ private:
ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return)
: This(This), Return(Return) { }
-
- bool isEmpty() const { return This.isEmpty() && Return.isEmpty(); }
+
+ friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) {
+ return LHS.This == RHS.This && LHS.Return == RHS.Return;
+ }
+
+ bool isEmpty() const { return This.isEmpty() && Return.isEmpty(); }
};
typedef llvm::DenseMap<uint64_t, ThunkInfo> ThunksInfoMapTy;
@@ -1215,6 +1232,16 @@ private:
/// Thunks - The thunks by vtable index in the vtable currently being built.
ThunksInfoMapTy Thunks;
+ typedef llvm::DenseMap<const CXXMethodDecl *,
+ llvm::SmallVector<ThunkInfo, 1> > MethodThunksMapTy;
+
+ /// MethodThunks - A map that contains all the thunks needed for all methods
+ /// in the vtable currently being built.
+ MethodThunksMapTy MethodThunks;
+
+ /// AddThunk - Add a thunk for the given method.
+ void AddThunk(const CXXMethodDecl *MD, ThunkInfo &Thunk);
+
/// ComputeThisAdjustments - Compute the 'this' pointer adjustments for the
/// part of the vtable we're currently building.
void ComputeThisAdjustments();
@@ -1330,6 +1357,20 @@ public:
void dumpLayout(llvm::raw_ostream&);
};
+void VtableBuilder::AddThunk(const CXXMethodDecl *MD, ThunkInfo &Thunk) {
+ if (isBuildingConstructorVtable())
+ return;
+
+ llvm::SmallVector<ThunkInfo, 1> &ThunksVector = MethodThunks[MD];
+
+ // Check if we have this thunk already.
+ if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=
+ ThunksVector.end())
+ return;
+
+ ThunksVector.push_back(Thunk);
+}
+
/// OverridesMethodInBases - Checks whether whether this virtual member
/// function overrides a member function in any of the given bases.
/// Returns the overridden member function, or null if none was found.
@@ -1382,6 +1423,8 @@ void VtableBuilder::ComputeThisAdjustments() {
// Add an adjustment for the deleting destructor as well.
Thunks[VtableIndex + 1].This = ThisAdjustment;
}
+
+ AddThunk(Overrider.Method, Thunks[VtableIndex]);
}
/// Clear the method info map.
@@ -2182,20 +2225,25 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
Out << '\n';
- if (!isBuildingConstructorVtable() && MostDerivedClass->getNumVBases()) {
- Out << "Virtual base offset offsets for '";
- Out << MostDerivedClass->getQualifiedNameAsString() << "'.\n";
-
+ if (isBuildingConstructorVtable())
+ return;
+
+ if (MostDerivedClass->getNumVBases()) {
// We store the virtual base class names and their offsets in a map to get
// a stable order.
- std::map<std::string, int64_t> ClassNamesAndOffsets;
+ std::map<std::string, int64_t> ClassNamesAndOffsets;
for (VBaseOffsetOffsetsMapTy::const_iterator I = VBaseOffsetOffsets.begin(),
E = VBaseOffsetOffsets.end(); I != E; ++I) {
std::string ClassName = I->first->getQualifiedNameAsString();
int64_t OffsetOffset = I->second;
ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
}
+
+ Out << "Virtual base offset offsets for '";
+ Out << MostDerivedClass->getQualifiedNameAsString() << "' (";
+ Out << ClassNamesAndOffsets.size();
+ Out << (ClassNamesAndOffsets.size() == 1 ? " entry" : " entries") << ").\n";
for (std::map<std::string, int64_t>::const_iterator I =
ClassNamesAndOffsets.begin(), E = ClassNamesAndOffsets.end();
@@ -2204,6 +2252,52 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
Out << "\n";
}
+
+ if (!MethodThunks.empty()) {
+
+ // We store the method names in a map to get a stable order.
+ std::map<std::string, const CXXMethodDecl *> MethodNamesAndDecls;
+
+ for (MethodThunksMapTy::const_iterator I = MethodThunks.begin(),
+ E = MethodThunks.end(); I != E; ++I) {
+ const CXXMethodDecl *MD = I->first;
+ std::string MethodName =
+ PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual,
+ MD);
+
+ MethodNamesAndDecls.insert(std::make_pair(MethodName, MD));
+ }
+
+ for (std::map<std::string, const CXXMethodDecl *>::const_iterator I =
+ MethodNamesAndDecls.begin(), E = MethodNamesAndDecls.end();
+ I != E; ++I) {
+ const std::string &MethodName = I->first;
+ const CXXMethodDecl *MD = I->second;
+ const llvm::SmallVector<ThunkInfo, 1> &ThunksVector = MethodThunks[MD];
+
+ Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size();
+ Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n";
+
+ for (unsigned I = 0, E = ThunksVector.size(); I != E; ++I) {
+ const ThunkInfo &Thunk = ThunksVector[I];
+
+ Out << llvm::format("%4d | ", I);
+
+ // If this function pointer has a 'this' pointer adjustment, dump it.
+ if (!Thunk.This.isEmpty()) {
+ Out << "this: ";
+ Out << Thunk.This.NonVirtual << " nv";
+
+ if (Thunk.This.VCallOffsetOffset) {
+ Out << ", " << Thunk.This.VCallOffsetOffset;
+ Out << " v";
+ }
+ }
+
+ Out << '\n';
+ }
+ }
+ }
}
}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 88d6413..bd12c4a 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -1231,6 +1231,12 @@ public:
llvm::Constant **Decls,
unsigned NumDecls);
+ /// GenerateCXXGlobalDtorFunc - Generates code for destroying global
+ /// variables.
+ void GenerateCXXGlobalDtorFunc(llvm::Function *Fn,
+ const std::vector<std::pair<llvm::Constant*,
+ llvm::Constant*> > &DtorsAndObjects);
+
void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, const VarDecl *D);
void EmitCXXConstructExpr(llvm::Value *Dest, const CXXConstructExpr *E);
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index f41db14..b4b5bbd 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -81,6 +81,7 @@ void CodeGenModule::createObjCRuntime() {
void CodeGenModule::Release() {
EmitDeferred();
EmitCXXGlobalInitFunc();
+ EmitCXXGlobalDtorFunc();
if (Runtime)
if (llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction())
AddGlobalCtor(ObjCInitFunction);
@@ -163,15 +164,15 @@ void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
}
}
-const char *CodeGenModule::getMangledName(const GlobalDecl &GD) {
+void CodeGenModule::getMangledName(MangleBuffer &Buffer, GlobalDecl GD) {
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
if (const CXXConstructorDecl *D = dyn_cast<CXXConstructorDecl>(ND))
- return getMangledCXXCtorName(D, GD.getCtorType());
+ return getMangledCXXCtorName(Buffer, D, GD.getCtorType());
if (const CXXDestructorDecl *D = dyn_cast<CXXDestructorDecl>(ND))
- return getMangledCXXDtorName(D, GD.getDtorType());
+ return getMangledCXXDtorName(Buffer, D, GD.getDtorType());
- return getMangledName(ND);
+ return getMangledName(Buffer, ND);
}
/// \brief Retrieves the mangled name for the given declaration.
@@ -180,23 +181,19 @@ const char *CodeGenModule::getMangledName(const GlobalDecl &GD) {
/// const char* containing the mangled name. Otherwise, returns
/// the unmangled name.
///
-const char *CodeGenModule::getMangledName(const NamedDecl *ND) {
+void CodeGenModule::getMangledName(MangleBuffer &Buffer,
+ const NamedDecl *ND) {
if (!getMangleContext().shouldMangleDeclName(ND)) {
assert(ND->getIdentifier() && "Attempt to mangle unnamed decl.");
- return ND->getNameAsCString();
+ Buffer.setString(ND->getNameAsCString());
+ return;
}
- llvm::SmallString<256> Name;
- getMangleContext().mangleName(ND, Name);
- Name += '\0';
- return UniqueMangledName(Name.begin(), Name.end());
+ getMangleContext().mangleName(ND, Buffer.getBuffer());
}
-const char *CodeGenModule::UniqueMangledName(const char *NameStart,
- const char *NameEnd) {
- assert(*(NameEnd - 1) == '\0' && "Mangled name must be null terminated!");
-
- return MangledNames.GetOrCreateValue(NameStart, NameEnd).getKeyData();
+llvm::GlobalValue *CodeGenModule::GetGlobalValue(llvm::StringRef Name) {
+ return getModule().getNamedValue(Name);
}
/// AddGlobalCtor - Add a function to the list that will be called before
@@ -505,11 +502,12 @@ void CodeGenModule::EmitDeferred() {
GlobalDecl D = DeferredDeclsToEmit.back();
DeferredDeclsToEmit.pop_back();
- // The mangled name for the decl must have been emitted in GlobalDeclMap.
// Look it up to see if it was defined with a stronger definition (e.g. an
// extern inline function with a strong function redefinition). If so,
// just ignore the deferred decl.
- llvm::GlobalValue *CGRef = GlobalDeclMap[getMangledName(D)];
+ MangleBuffer Name;
+ getMangledName(Name, D);
+ llvm::GlobalValue *CGRef = GetGlobalValue(Name);
assert(CGRef && "Deferred decl wasn't referenced?");
if (!CGRef->isDeclaration())
@@ -644,18 +642,14 @@ llvm::Constant *CodeGenModule::GetWeakRefReference(const ValueDecl *VD) {
const llvm::Type *DeclTy = getTypes().ConvertTypeForMem(VD->getType());
- // Unique the name through the identifier table.
- const char *AliaseeName =
- getContext().Idents.get(AA->getAliasee()).getNameStart();
-
// See if there is already something with the target's name in the module.
- llvm::GlobalValue *Entry = GlobalDeclMap[AliaseeName];
+ llvm::GlobalValue *Entry = GetGlobalValue(AA->getAliasee());
llvm::Constant *Aliasee;
if (isa<llvm::FunctionType>(DeclTy))
- Aliasee = GetOrCreateLLVMFunction(AliaseeName, DeclTy, GlobalDecl());
+ Aliasee = GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, GlobalDecl());
else
- Aliasee = GetOrCreateLLVMGlobal(AliaseeName,
+ Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(),
llvm::PointerType::getUnqual(DeclTy), 0);
if (!Entry) {
llvm::GlobalValue* F = cast<llvm::GlobalValue>(Aliasee);
@@ -676,7 +670,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
// If this is an alias definition (which otherwise looks like a declaration)
// emit it now.
if (Global->hasAttr<AliasAttr>())
- return EmitAliasDefinition(Global);
+ return EmitAliasDefinition(GD);
// Ignore declarations, they will be emitted on their first use.
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) {
@@ -696,8 +690,9 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
if (MayDeferGeneration(Global)) {
// If the value has already been used, add it directly to the
// DeferredDeclsToEmit list.
- const char *MangledName = getMangledName(GD);
- if (GlobalDeclMap.count(MangledName))
+ MangleBuffer MangledName;
+ getMangledName(MangledName, GD);
+ if (GetGlobalValue(MangledName))
DeferredDeclsToEmit.push_back(GD);
else {
// Otherwise, remember that we saw a deferred decl with this name. The
@@ -753,11 +748,12 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
///
/// If D is non-null, it specifies a decl that correspond to this. This is used
/// to set the attributes on the function when it is first created.
-llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName,
- const llvm::Type *Ty,
- GlobalDecl D) {
+llvm::Constant *
+CodeGenModule::GetOrCreateLLVMFunction(llvm::StringRef MangledName,
+ const llvm::Type *Ty,
+ GlobalDecl D) {
// Lookup the entry, lazily creating it if necessary.
- llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
+ llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (Entry) {
if (WeakRefReferences.count(Entry)) {
const FunctionDecl *FD = cast_or_null<FunctionDecl>(D.getDecl());
@@ -786,17 +782,15 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName,
}
llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty),
llvm::Function::ExternalLinkage,
- "", &getModule());
- F->setName(MangledName);
+ MangledName, &getModule());
+ assert(F->getName() == MangledName && "name was uniqued!");
if (D.getDecl())
SetFunctionAttributes(D, F, IsIncompleteFunction);
- Entry = F;
// This is the first use or definition of a mangled name. If there is a
// deferred decl with this name, remember that we need to emit it at the end
// of the file.
- llvm::DenseMap<const char*, GlobalDecl>::iterator DDI =
- DeferredDecls.find(MangledName);
+ llvm::StringMap<GlobalDecl>::iterator DDI = DeferredDecls.find(MangledName);
if (DDI != DeferredDecls.end()) {
// Move the potentially referenced deferred decl to the DeferredDeclsToEmit
// list, and remove it from DeferredDecls (since we don't need it anymore).
@@ -839,16 +833,16 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD,
// If there was no specific requested type, just convert it now.
if (!Ty)
Ty = getTypes().ConvertType(cast<ValueDecl>(GD.getDecl())->getType());
- return GetOrCreateLLVMFunction(getMangledName(GD), Ty, GD);
+ MangleBuffer MangledName;
+ getMangledName(MangledName, GD);
+ return GetOrCreateLLVMFunction(MangledName, Ty, GD);
}
/// CreateRuntimeFunction - Create a new runtime function with the specified
/// type and name.
llvm::Constant *
CodeGenModule::CreateRuntimeFunction(const llvm::FunctionType *FTy,
- const char *Name) {
- // Convert Name to be a uniqued string from the IdentifierInfo table.
- Name = getContext().Idents.get(Name).getNameStart();
+ llvm::StringRef Name) {
return GetOrCreateLLVMFunction(Name, FTy, GlobalDecl());
}
@@ -870,11 +864,12 @@ static bool DeclIsConstantGlobal(ASTContext &Context, const VarDecl *D) {
///
/// If D is non-null, it specifies a decl that correspond to this. This is used
/// to set the attributes on the global when it is first created.
-llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName,
- const llvm::PointerType*Ty,
- const VarDecl *D) {
+llvm::Constant *
+CodeGenModule::GetOrCreateLLVMGlobal(llvm::StringRef MangledName,
+ const llvm::PointerType *Ty,
+ const VarDecl *D) {
// Lookup the entry, lazily creating it if necessary.
- llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
+ llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (Entry) {
if (WeakRefReferences.count(Entry)) {
if (D && !D->hasAttr<WeakAttr>())
@@ -893,8 +888,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName,
// This is the first use or definition of a mangled name. If there is a
// deferred decl with this name, remember that we need to emit it at the end
// of the file.
- llvm::DenseMap<const char*, GlobalDecl>::iterator DDI =
- DeferredDecls.find(MangledName);
+ llvm::StringMap<GlobalDecl>::iterator DDI = DeferredDecls.find(MangledName);
if (DDI != DeferredDecls.end()) {
// Move the potentially referenced deferred decl to the DeferredDeclsToEmit
// list, and remove it from DeferredDecls (since we don't need it anymore).
@@ -905,9 +899,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName,
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(getModule(), Ty->getElementType(), false,
llvm::GlobalValue::ExternalLinkage,
- 0, "", 0,
+ 0, MangledName, 0,
false, Ty->getAddressSpace());
- GV->setName(MangledName);
// Handle things which are present even on external declarations.
if (D) {
@@ -926,7 +919,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName,
GV->setThreadLocal(D->isThreadSpecified());
}
- return Entry = GV;
+ return GV;
}
@@ -943,16 +936,17 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
const llvm::PointerType *PTy =
llvm::PointerType::get(Ty, ASTTy.getAddressSpace());
- return GetOrCreateLLVMGlobal(getMangledName(D), PTy, D);
+
+ MangleBuffer MangledName;
+ getMangledName(MangledName, D);
+ return GetOrCreateLLVMGlobal(MangledName, PTy, D);
}
/// CreateRuntimeVariable - Create a new runtime global variable with the
/// specified type and name.
llvm::Constant *
CodeGenModule::CreateRuntimeVariable(const llvm::Type *Ty,
- const char *Name) {
- // Convert Name to be a uniqued string from the IdentifierInfo table.
- Name = getContext().Idents.get(Name).getNameStart();
+ llvm::StringRef Name) {
return GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), 0);
}
@@ -963,8 +957,9 @@ void CodeGenModule::EmitTentativeDefinition(const VarDecl *D) {
// If we have not seen a reference to this variable yet, place it
// into the deferred declarations table to be emitted if needed
// later.
- const char *MangledName = getMangledName(D);
- if (GlobalDeclMap.count(MangledName) == 0) {
+ MangleBuffer MangledName;
+ getMangledName(MangledName, D);
+ if (!GetGlobalValue(MangledName)) {
DeferredDecls[MangledName] = D;
return;
}
@@ -1133,12 +1128,11 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
GV->getType()->getElementType() != InitType ||
GV->getType()->getAddressSpace() != ASTTy.getAddressSpace()) {
- // Remove the old entry from GlobalDeclMap so that we'll create a new one.
- GlobalDeclMap.erase(getMangledName(D));
+ // Move the old entry aside so that we'll create a new one.
+ Entry->setName(llvm::StringRef());
// Make a new global with the correct type, this is now guaranteed to work.
GV = cast<llvm::GlobalVariable>(GetAddrOfGlobalVar(D, InitType));
- GV->takeName(cast<llvm::GlobalValue>(Entry));
// Replace all uses of the old global with the new global
llvm::Constant *NewPtrForOldDecl =
@@ -1296,11 +1290,10 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
//
// This happens if there is a prototype for a function
// (e.g. "int f()") and then a definition of a different type
- // (e.g. "int f(int x)"). Start by making a new function of the
- // correct type, RAUW, then steal the name.
- GlobalDeclMap.erase(getMangledName(D));
+ // (e.g. "int f(int x)"). Move the old function aside so that it
+ // doesn't interfere with GetAddrOfFunction.
+ OldFn->setName(llvm::StringRef());
llvm::Function *NewFn = cast<llvm::Function>(GetAddrOfFunction(GD, Ty));
- NewFn->takeName(OldFn);
// If this is an implementation of a function without a prototype, try to
// replace any existing uses of the function (which may be calls) with uses
@@ -1336,23 +1329,29 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
AddGlobalDtor(Fn, DA->getPriority());
}
-void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
+void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
+ const ValueDecl *D = cast<ValueDecl>(GD.getDecl());
const AliasAttr *AA = D->getAttr<AliasAttr>();
assert(AA && "Not an alias?");
- const llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
+ MangleBuffer MangledName;
+ getMangledName(MangledName, GD);
- // Unique the name through the identifier table.
- const char *AliaseeName =
- getContext().Idents.get(AA->getAliasee()).getNameStart();
+ // If there is a definition in the module, then it wins over the alias.
+ // This is dubious, but allow it to be safe. Just ignore the alias.
+ llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+ if (Entry && !Entry->isDeclaration())
+ return;
+
+ const llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType());
// Create a reference to the named value. This ensures that it is emitted
// if a deferred decl.
llvm::Constant *Aliasee;
if (isa<llvm::FunctionType>(DeclTy))
- Aliasee = GetOrCreateLLVMFunction(AliaseeName, DeclTy, GlobalDecl());
+ Aliasee = GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, GlobalDecl());
else
- Aliasee = GetOrCreateLLVMGlobal(AliaseeName,
+ Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(),
llvm::PointerType::getUnqual(DeclTy), 0);
// Create the new alias itself, but don't set a name yet.
@@ -1361,18 +1360,9 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
llvm::Function::ExternalLinkage,
"", Aliasee, &getModule());
- // See if there is already something with the alias' name in the module.
- const char *MangledName = getMangledName(D);
- llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
-
- if (Entry && !Entry->isDeclaration()) {
- // If there is a definition in the module, then it wins over the alias.
- // This is dubious, but allow it to be safe. Just ignore the alias.
- GA->eraseFromParent();
- return;
- }
-
if (Entry) {
+ assert(Entry->isDeclaration());
+
// If there is a declaration in the module, then we had an extern followed
// by the alias, as in:
// extern int test6();
@@ -1380,16 +1370,15 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {
// int test6() __attribute__((alias("test7")));
//
// Remove it and replace uses of it with the alias.
+ GA->takeName(Entry);
Entry->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(GA,
Entry->getType()));
Entry->eraseFromParent();
+ } else {
+ GA->setName(MangledName.getString());
}
- // Now we know that there is no conflict, set the name.
- Entry = GA;
- GA->setName(MangledName);
-
// Set attributes which are particular to an alias; this is a
// specialization of the attributes which may be set on a global
// variable/function.
@@ -1426,8 +1415,6 @@ llvm::Value *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD,
const llvm::FunctionType *Ty =
cast<llvm::FunctionType>(getTypes().ConvertType(FD->getType()));
- // Unique the name through the identifier table.
- Name = getContext().Idents.get(Name).getNameStart();
return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl(FD));
}
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 9077ade..febb856 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -73,7 +73,7 @@ namespace CodeGen {
class CodeGenFunction;
class CGDebugInfo;
class CGObjCRuntime;
-
+ class MangleBuffer;
/// CodeGenModule - This class organizes the cross-function state that is used
/// while generating LLVM code.
@@ -103,38 +103,16 @@ class CodeGenModule : public BlockModule {
llvm::Function *MemMoveFn;
llvm::Function *MemSetFn;
- /// GlobalDeclMap - Mapping of decl names (represented as unique
- /// character pointers from either the identifier table or the set
- /// of mangled names) to global variables we have already
- /// emitted. Note that the entries in this map are the actual
- /// globals and therefore may not be of the same type as the decl,
- /// they should be bitcasted on retrieval. Also note that the
- /// globals are keyed on their source mangled name, not the global name
- /// (which may change with attributes such as asm-labels). The key
- /// to this map should be generated using getMangledName().
- ///
- /// Note that this map always lines up exactly with the contents of the LLVM
- /// IR symbol table, but this is quicker to query since it is doing uniqued
- /// pointer lookups instead of full string lookups.
- llvm::DenseMap<const char*, llvm::GlobalValue*> GlobalDeclMap;
-
// WeakRefReferences - A set of references that have only been seen via
// a weakref so far. This is used to remove the weak of the reference if we ever
// see a direct reference or a definition.
llvm::SmallPtrSet<llvm::GlobalValue*, 10> WeakRefReferences;
- /// \brief Contains the strings used for mangled names.
- ///
- /// FIXME: Eventually, this should map from the semantic/canonical
- /// declaration for each global entity to its mangled name (if it
- /// has one).
- llvm::StringSet<> MangledNames;
-
/// DeferredDecls - This contains all the decls which have definitions but
/// which are deferred for emission and therefore should only be output if
/// they are actually used. If a decl is in this, then it is known to have
- /// not been referenced yet. The key to this map is a uniqued mangled name.
- llvm::DenseMap<const char*, GlobalDecl> DeferredDecls;
+ /// not been referenced yet.
+ llvm::StringMap<GlobalDecl> DeferredDecls;
/// DeferredDeclsToEmit - This is a list of deferred decls which we have seen
/// that *are* actually referenced. These get code generated when the module
@@ -160,10 +138,14 @@ class CodeGenModule : public BlockModule {
llvm::StringMap<llvm::Constant*> CFConstantStringMap;
llvm::StringMap<llvm::Constant*> ConstantStringMap;
- /// CXXGlobalInits - Variables with global initializers that need to run
+ /// CXXGlobalInits - Global variables with initializers that need to run
/// before main.
std::vector<llvm::Constant*> CXXGlobalInits;
+ /// CXXGlobalDtors - Global destructor functions and arguments that need to
+ /// run on termination.
+ std::vector<std::pair<llvm::Constant*,llvm::Constant*> > CXXGlobalDtors;
+
/// CFConstantStringClassRef - Cached reference to the class for constant
/// strings. This value has type int * but is actually an Obj-C class pointer.
llvm::Constant *CFConstantStringClassRef;
@@ -343,14 +325,18 @@ public:
void AddAnnotation(llvm::Constant *C) { Annotations.push_back(C); }
+ /// AddCXXDtorEntry - Add a destructor and object to add to the C++ global
+ /// destructor function.
+ void AddCXXDtorEntry(llvm::Constant *DtorFn, llvm::Constant *Object);
+
/// CreateRuntimeFunction - Create a new runtime function with the specified
/// type and name.
llvm::Constant *CreateRuntimeFunction(const llvm::FunctionType *Ty,
- const char *Name);
+ llvm::StringRef Name);
/// CreateRuntimeVariable - Create a new runtime global variable with the
/// specified type and name.
llvm::Constant *CreateRuntimeVariable(const llvm::Type *Ty,
- const char *Name);
+ llvm::StringRef Name);
void UpdateCompletedType(const TagDecl *TD) {
// Make sure that this type is translated.
@@ -422,13 +408,14 @@ public:
AttributeListType &PAL,
unsigned &CallingConv);
- const char *getMangledName(const GlobalDecl &D);
-
- const char *getMangledName(const NamedDecl *ND);
- const char *getMangledCXXCtorName(const CXXConstructorDecl *D,
- CXXCtorType Type);
- const char *getMangledCXXDtorName(const CXXDestructorDecl *D,
- CXXDtorType Type);
+ void getMangledName(MangleBuffer &Buffer, GlobalDecl D);
+ void getMangledName(MangleBuffer &Buffer, const NamedDecl *ND);
+ void getMangledCXXCtorName(MangleBuffer &Buffer,
+ const CXXConstructorDecl *D,
+ CXXCtorType Type);
+ void getMangledCXXDtorName(MangleBuffer &Buffer,
+ const CXXDestructorDecl *D,
+ CXXDtorType Type);
void EmitTentativeDefinition(const VarDecl *D);
@@ -456,14 +443,12 @@ public:
std::vector<const CXXRecordDecl*> DeferredVtables;
private:
- /// UniqueMangledName - Unique a name by (if necessary) inserting it into the
- /// MangledNames string map.
- const char *UniqueMangledName(const char *NameStart, const char *NameEnd);
+ llvm::GlobalValue *GetGlobalValue(llvm::StringRef Ref);
- llvm::Constant *GetOrCreateLLVMFunction(const char *MangledName,
+ llvm::Constant *GetOrCreateLLVMFunction(llvm::StringRef MangledName,
const llvm::Type *Ty,
GlobalDecl D);
- llvm::Constant *GetOrCreateLLVMGlobal(const char *MangledName,
+ llvm::Constant *GetOrCreateLLVMGlobal(llvm::StringRef MangledName,
const llvm::PointerType *PTy,
const VarDecl *D);
@@ -492,7 +477,7 @@ private:
void EmitGlobalFunctionDefinition(GlobalDecl GD);
void EmitGlobalVarDefinition(const VarDecl *D);
- void EmitAliasDefinition(const ValueDecl *D);
+ void EmitAliasDefinition(GlobalDecl GD);
void EmitObjCPropertyImplementations(const ObjCImplementationDecl *D);
// C++ related functions.
@@ -519,9 +504,12 @@ private:
/// a C++ destructor Decl.
void EmitCXXDestructor(const CXXDestructorDecl *D, CXXDtorType Type);
- /// EmitCXXGlobalInitFunc - Emit a function that initializes C++ globals.
+ /// EmitCXXGlobalInitFunc - Emit the function that initializes C++ globals.
void EmitCXXGlobalInitFunc();
+ /// EmitCXXGlobalDtorFunc - Emit the function that destroys C++ globals.
+ void EmitCXXGlobalDtorFunc();
+
void EmitCXXGlobalVarDeclInitFunc(const VarDecl *D);
// FIXME: Hardcoding priority here is gross.
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 32555ab..f2a73f1 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -469,8 +469,26 @@ void CXXNameMangler::mangleUnresolvedScope(NestedNameSpecifier *Qualifier) {
mangleName(Qualifier->getAsNamespace());
break;
case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate:
- mangleType(QualType(Qualifier->getAsType(), 0));
+ case NestedNameSpecifier::TypeSpecWithTemplate: {
+ const Type *QTy = Qualifier->getAsType();
+
+ if (const TemplateSpecializationType *TST =
+ dyn_cast<TemplateSpecializationType>(QTy)) {
+ if (!mangleSubstitution(QualType(TST, 0))) {
+ TemplateDecl *TD = TST->getTemplateName().getAsTemplateDecl();
+ assert(TD && "FIXME: Support dependent template names");
+ mangleTemplatePrefix(TD);
+ TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
+ mangleTemplateArgs(*TemplateParameters, TST->getArgs(),
+ TST->getNumArgs());
+ addSubstitution(QualType(TST, 0));
+ }
+ } else {
+ // We use the QualType mangle type variant here because it handles
+ // substitutions.
+ mangleType(QualType(QTy, 0));
+ }
+ }
break;
case NestedNameSpecifier::Identifier:
// Member expressions can have these without prefixes.
@@ -1144,29 +1162,8 @@ void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
void CXXNameMangler::mangleType(const TypenameType *T) {
// Typename types are always nested
Out << 'N';
-
- const Type *QTy = T->getQualifier()->getAsType();
- if (const TemplateSpecializationType *TST =
- dyn_cast<TemplateSpecializationType>(QTy)) {
- if (!mangleSubstitution(QualType(TST, 0))) {
- TemplateDecl *TD = TST->getTemplateName().getAsTemplateDecl();
- assert(TD && "FIXME: Support dependent template names");
- mangleTemplatePrefix(TD);
- TemplateParameterList *TemplateParameters = TD->getTemplateParameters();
- mangleTemplateArgs(*TemplateParameters, TST->getArgs(),
- TST->getNumArgs());
- addSubstitution(QualType(TST, 0));
- }
- } else if (const TemplateTypeParmType *TTPT =
- dyn_cast<TemplateTypeParmType>(QTy)) {
- // We use the QualType mangle type variant here because it handles
- // substitutions.
- mangleType(QualType(TTPT, 0));
- } else
- assert(false && "Unhandled type!");
-
+ mangleUnresolvedScope(T->getQualifier());
mangleSourceName(T->getIdentifier());
-
Out << 'E';
}
diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h
index 97f94b6..62656b9 100644
--- a/lib/CodeGen/Mangle.h
+++ b/lib/CodeGen/Mangle.h
@@ -21,10 +21,8 @@
#include "CGCXX.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/DenseMap.h"
-
-namespace llvm {
- template<typename T> class SmallVectorImpl;
-}
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallString.h"
namespace clang {
class ASTContext;
@@ -37,6 +35,33 @@ namespace clang {
namespace CodeGen {
class CovariantThunkAdjustment;
class ThunkAdjustment;
+
+/// MangleBuffer - a convenient class for storing a name which is
+/// either the result of a mangling or is a constant string with
+/// external memory ownership.
+class MangleBuffer {
+public:
+ void setString(llvm::StringRef Ref) {
+ String = Ref;
+ }
+
+ llvm::SmallVectorImpl<char> &getBuffer() {
+ return Buffer;
+ }
+
+ llvm::StringRef getString() const {
+ if (!String.empty()) return String;
+ return Buffer.str();
+ }
+
+ operator llvm::StringRef() const {
+ return getString();
+ }
+
+private:
+ llvm::StringRef String;
+ llvm::SmallString<256> Buffer;
+};
/// MangleContext - Context for tracking state which persists across multiple
/// calls to the C++ name mangler.
OpenPOWER on IntegriCloud