From 0ce2b875072597713fc89a352cacafcdd7278a75 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 11 Apr 2014 23:45:01 +0000 Subject: [PATCH] Follow-up to r205999: Emit an artificial location (valid scope, line 0) for CXXGlobalInit/Dtor helper functions. This makes _GLOBAL__I_a regain its DW_AT_high/low_pc in the debug info. Thanks to echristo for catching this! llvm-svn: 206088 --- clang/lib/CodeGen/CGDeclCXX.cpp | 93 +++++++++++++----------- clang/test/CodeGenCXX/globalinit-loc.cpp | 3 +- 2 files changed, 54 insertions(+), 42 deletions(-) diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 640e9fa92de2..7a0ef8948e4f 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -431,43 +431,49 @@ void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, ArrayRef Decls, llvm::GlobalVariable *Guard) { - StartFunction(GlobalDecl(), getContext().VoidTy, Fn, - getTypes().arrangeNullaryFunction(), FunctionArgList()); + { + ArtificialLocation AL(*this, Builder); + StartFunction(GlobalDecl(), getContext().VoidTy, Fn, + getTypes().arrangeNullaryFunction(), FunctionArgList()); + // Emit an artificial location for this function. + AL.Emit(); - llvm::BasicBlock *ExitBlock = 0; - if (Guard) { - // If we have a guard variable, check whether we've already performed these - // initializations. This happens for TLS initialization functions. - llvm::Value *GuardVal = Builder.CreateLoad(Guard); - llvm::Value *Uninit = Builder.CreateIsNull(GuardVal, "guard.uninitialized"); - // Mark as initialized before initializing anything else. If the - // initializers use previously-initialized thread_local vars, that's - // probably supposed to be OK, but the standard doesn't say. - Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(), 1), Guard); - llvm::BasicBlock *InitBlock = createBasicBlock("init"); - ExitBlock = createBasicBlock("exit"); - Builder.CreateCondBr(Uninit, InitBlock, ExitBlock); - EmitBlock(InitBlock); - } + llvm::BasicBlock *ExitBlock = 0; + if (Guard) { + // If we have a guard variable, check whether we've already performed + // these initializations. This happens for TLS initialization functions. + llvm::Value *GuardVal = Builder.CreateLoad(Guard); + llvm::Value *Uninit = Builder.CreateIsNull(GuardVal, + "guard.uninitialized"); + // Mark as initialized before initializing anything else. If the + // initializers use previously-initialized thread_local vars, that's + // probably supposed to be OK, but the standard doesn't say. + Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(),1), Guard); + llvm::BasicBlock *InitBlock = createBasicBlock("init"); + ExitBlock = createBasicBlock("exit"); + Builder.CreateCondBr(Uninit, InitBlock, ExitBlock); + EmitBlock(InitBlock); + } - RunCleanupsScope Scope(*this); + RunCleanupsScope Scope(*this); - // When building in Objective-C++ ARC mode, create an autorelease pool - // around the global initializers. - if (getLangOpts().ObjCAutoRefCount && getLangOpts().CPlusPlus) { - llvm::Value *token = EmitObjCAutoreleasePoolPush(); - EmitObjCAutoreleasePoolCleanup(token); - } + // When building in Objective-C++ ARC mode, create an autorelease pool + // around the global initializers. + if (getLangOpts().ObjCAutoRefCount && getLangOpts().CPlusPlus) { + llvm::Value *token = EmitObjCAutoreleasePoolPush(); + EmitObjCAutoreleasePoolCleanup(token); + } - for (unsigned i = 0, e = Decls.size(); i != e; ++i) - if (Decls[i]) - EmitRuntimeCall(Decls[i]); + for (unsigned i = 0, e = Decls.size(); i != e; ++i) + if (Decls[i]) + EmitRuntimeCall(Decls[i]); - Scope.ForceCleanup(); + Scope.ForceCleanup(); - if (ExitBlock) { - Builder.CreateBr(ExitBlock); - EmitBlock(ExitBlock); + if (ExitBlock) { + Builder.CreateBr(ExitBlock); + EmitBlock(ExitBlock); + } } FinishFunction(); @@ -476,17 +482,22 @@ CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, void CodeGenFunction::GenerateCXXGlobalDtorsFunc(llvm::Function *Fn, const std::vector > &DtorsAndObjects) { - StartFunction(GlobalDecl(), getContext().VoidTy, Fn, - getTypes().arrangeNullaryFunction(), FunctionArgList()); + { + ArtificialLocation AL(*this, Builder); + StartFunction(GlobalDecl(), getContext().VoidTy, Fn, + getTypes().arrangeNullaryFunction(), FunctionArgList()); + // Emit an artificial location for this function. + AL.Emit(); - // Emit the dtors, in reverse order from construction. - for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) { - llvm::Value *Callee = DtorsAndObjects[e - i - 1].first; - llvm::CallInst *CI = Builder.CreateCall(Callee, - DtorsAndObjects[e - i - 1].second); - // Make sure the call and the callee agree on calling convention. - if (llvm::Function *F = dyn_cast(Callee)) - CI->setCallingConv(F->getCallingConv()); + // Emit the dtors, in reverse order from construction. + for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) { + llvm::Value *Callee = DtorsAndObjects[e - i - 1].first; + llvm::CallInst *CI = Builder.CreateCall(Callee, + DtorsAndObjects[e - i - 1].second); + // Make sure the call and the callee agree on calling convention. + if (llvm::Function *F = dyn_cast(Callee)) + CI->setCallingConv(F->getCallingConv()); + } } FinishFunction(); diff --git a/clang/test/CodeGenCXX/globalinit-loc.cpp b/clang/test/CodeGenCXX/globalinit-loc.cpp index bf3340c15720..c6c27e379d6e 100644 --- a/clang/test/CodeGenCXX/globalinit-loc.cpp +++ b/clang/test/CodeGenCXX/globalinit-loc.cpp @@ -5,8 +5,9 @@ // with any source location. // // CHECK: define internal void @_GLOBAL__I_a -// CHECK-NOT: !dbg +// CHECK: !dbg ![[DBG:.*]] // CHECK: "_GLOBAL__I_a", i32 0, {{.*}}, i32 0} ; [ DW_TAG_subprogram ] [line 0] [local] [def] +// CHECK: ![[DBG]] = metadata !{i32 0, i32 0, # 99 "someheader.h" class A { public: