diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-03-21 10:50:08 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-03-21 10:50:08 +0000 |
commit | 1e255aab650a7fa2047fd953cae65b12215280af (patch) | |
tree | 508d4388db78f87d35bf26a0400b4b03bc4c1f13 /lib/CodeGen | |
parent | 1033b7c1e32962948b01a25145829f17bc70a8de (diff) | |
download | FreeBSD-src-1e255aab650a7fa2047fd953cae65b12215280af.zip FreeBSD-src-1e255aab650a7fa2047fd953cae65b12215280af.tar.gz |
Update clang to r99115.
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGBuiltin.cpp | 76 | ||||
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 55 | ||||
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 20 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 15 | ||||
-rw-r--r-- | lib/CodeGen/CGDeclCXX.cpp | 48 | ||||
-rw-r--r-- | lib/CodeGen/CGException.cpp | 34 | ||||
-rw-r--r-- | lib/CodeGen/CGObjCGNU.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 108 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 6 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 159 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 72 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 45 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.h | 33 |
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. |