From 30c0d27b61e38ad6038eeb8650f0dac83056c75b Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 3 May 2013 00:44:13 +0000 Subject: [PATCH] Attempt to un-break the gdb buildbot. - Use the debug location of the return expression for the cleanup code if the return expression is trivially evaluatable, regardless of the number of stop points in the function. - Ensure that any EH code in the cleanup still gets the line number of the closing } of the lexical scope. - Added a testcase with EH in the cleanup. rdar://problem/13442648 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180982 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCleanup.cpp | 12 +++++++++--- lib/CodeGen/CGStmt.cpp | 7 ++++--- lib/CodeGen/CodeGenFunction.cpp | 20 ++++++++++---------- lib/CodeGen/CodeGenFunction.h | 16 ++++++++++------ test/CodeGenCXX/linetable-cleanup.cpp | 24 ++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 22 deletions(-) create mode 100644 test/CodeGenCXX/linetable-cleanup.cpp diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp index 861d31fb7f..ba6b56c267 100644 --- a/lib/CodeGen/CGCleanup.cpp +++ b/lib/CodeGen/CGCleanup.cpp @@ -371,7 +371,8 @@ void CodeGenFunction::ResolveBranchFixups(llvm::BasicBlock *Block) { } /// Pops cleanup blocks until the given savepoint is reached. -void CodeGenFunction::PopCleanupBlocks(EHScopeStack::stable_iterator Old) { +void CodeGenFunction::PopCleanupBlocks(EHScopeStack::stable_iterator Old, + SourceLocation EHLoc) { assert(Old.isValid()); while (EHStack.stable_begin() != Old) { @@ -383,7 +384,7 @@ void CodeGenFunction::PopCleanupBlocks(EHScopeStack::stable_iterator Old) { bool FallThroughIsBranchThrough = Old.strictlyEncloses(Scope.getEnclosingNormalCleanup()); - PopCleanupBlock(FallThroughIsBranchThrough); + PopCleanupBlock(FallThroughIsBranchThrough, EHLoc); } } @@ -532,7 +533,8 @@ static void destroyOptimisticNormalEntry(CodeGenFunction &CGF, /// Pops a cleanup block. If the block includes a normal cleanup, the /// current insertion point is threaded through the cleanup, as are /// any branch fixups on the cleanup. -void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { +void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough, + SourceLocation EHLoc) { assert(!EHStack.empty() && "cleanup stack is empty!"); assert(isa(*EHStack.begin()) && "top not a cleanup!"); EHCleanupScope &Scope = cast(*EHStack.begin()); @@ -833,6 +835,9 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { // Emit the EH cleanup if required. if (RequiresEHCleanup) { + if (CGDebugInfo *DI = getDebugInfo()) + DI->EmitLocation(Builder, EHLoc); + CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); EmitBlock(EHEntry); @@ -840,6 +845,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { // We only actually emit the cleanup code if the cleanup is either // active or was used before it was deactivated. if (EHActiveFlag || IsActive) { + cleanupFlags.setIsForEHCleanup(); EmitCleanup(*this, Fn, cleanupFlags, EHActiveFlag); } diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 73f66e0c8c..5e2ebe0d9c 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -38,8 +38,8 @@ void CodeGenFunction::EmitStopPoint(const Stmt *S) { Loc = S->getLocStart(); DI->EmitLocation(Builder, Loc); - if (++NumStopPoints == 1) - FirstStopPoint = Loc; + //if (++NumStopPoints == 1) + LastStopPoint = Loc; } } @@ -842,8 +842,9 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { } } + NumReturnExprs += 1; if (RV == 0 || RV->isEvaluatable(getContext())) - ++NumSimpleReturnExprs; + NumSimpleReturnExprs += 1; cleanupScope.ForceCleanup(); EmitBranchThroughCleanup(ReturnBlock); diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 122e95b266..9f97560600 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -44,7 +44,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) DebugInfo(0), DisableDebugInfo(false), CalleeWithThisReturn(0), DidCallStackSave(false), IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0), - NumStopPoints(0), NumSimpleReturnExprs(0), + NumReturnExprs(0), NumSimpleReturnExprs(0), CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0), CXXDefaultInitExprThis(0), CXXStructorImplicitParamDecl(0), CXXStructorImplicitParamValue(0), @@ -188,14 +188,14 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { assert(BreakContinueStack.empty() && "mismatched push/pop in break/continue stack!"); - // If the function contains only a single, simple return statement, - // the cleanup code may become the first breakpoint in the - // function. To be safe set the debug location for it to the - // location of the return statement. Otherwise point it to end of - // the function's lexical scope. + // If the function contains only a simple return statement, the + // cleanup code may become the first breakpoint in the function. To + // be safe, set the debug location for it to the location of the + // return statement. Otherwise point it to end of the function's + // lexical scope. if (CGDebugInfo *DI = getDebugInfo()) { - if (NumSimpleReturnExprs == 1 && NumStopPoints == 1) - DI->EmitLocation(Builder, FirstStopPoint); + if (NumSimpleReturnExprs == NumReturnExprs) + DI->EmitLocation(Builder, LastStopPoint); else DI->EmitLocation(Builder, EndLoc); } @@ -206,14 +206,14 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { // edges will be *really* confused. bool EmitRetDbgLoc = true; if (EHStack.stable_begin() != PrologueCleanupDepth) { - PopCleanupBlocks(PrologueCleanupDepth); + PopCleanupBlocks(PrologueCleanupDepth, EndLoc); // Make sure the line table doesn't jump back into the body for // the ret after it's been at EndLoc. EmitRetDbgLoc = false; if (CGDebugInfo *DI = getDebugInfo()) - if (NumSimpleReturnExprs == 1 && NumStopPoints == 1) + if (NumSimpleReturnExprs == NumReturnExprs) DI->EmitLocation(Builder, EndLoc); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 17df1dad3e..7c6e8d176b 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -784,7 +784,9 @@ public: /// PopCleanupBlock - Will pop the cleanup entry on the stack and /// process all branch fixups. - void PopCleanupBlock(bool FallThroughIsBranchThrough = false); + /// \param EHLoc - Optional debug location for EH code. + void PopCleanupBlock(bool FallThroughIsBranchThrough = false, + SourceLocation EHLoc=SourceLocation()); /// DeactivateCleanupBlock - Deactivates the given cleanup block. /// The block cannot be reactivated. Pops it if it's the top of the @@ -905,7 +907,9 @@ public: /// PopCleanupBlocks - Takes the old cleanup stack size and emits /// the cleanup blocks that have been added. - void PopCleanupBlocks(EHScopeStack::stable_iterator OldCleanupStackSize); + /// \param EHLoc - Optional debug location for EH code. + void PopCleanupBlocks(EHScopeStack::stable_iterator OldCleanupStackSize, + SourceLocation EHLoc=SourceLocation()); void ResolveBranchFixups(llvm::BasicBlock *Target); @@ -1206,14 +1210,14 @@ private: /// lazily by getUnreachableBlock(). llvm::BasicBlock *UnreachableBlock; - /// Counts of the number of distinct breakpoint locations in this function. - unsigned NumStopPoints; + /// Counts of the number return expressions in the function. + unsigned NumReturnExprs; /// Count the number of simple (constant) return expressions in the function. unsigned NumSimpleReturnExprs; - /// The first debug location (breakpoint) in the function. - SourceLocation FirstStopPoint; + /// The last regular (non-return) debug location (breakpoint) in the function. + SourceLocation LastStopPoint; public: /// A scope within which we are constructing the fields of an object which diff --git a/test/CodeGenCXX/linetable-cleanup.cpp b/test/CodeGenCXX/linetable-cleanup.cpp new file mode 100644 index 0000000000..4077af6d8e --- /dev/null +++ b/test/CodeGenCXX/linetable-cleanup.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin10 %s -o - | FileCheck %s + +// Check the line numbers for cleanup code with EH in combinatin with +// simple return expressions. + +// CHECK: define {{.*}}foo +// CHECK: call void @_ZN1CD1Ev(%class.C* {{.*}}), !dbg ![[CLEANUP:[0-9]+]] +// CHECK: ret i32 0, !dbg ![[RET:[0-9]+]] + +class C { +public: + ~C() {} + int i; +}; + +int foo() +{ + C c; + c.i = 42; + // This breakpoint should be at/before the cleanup code. + // CHECK: ![[CLEANUP]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} + return 0; + // CHECK: ![[RET]] = metadata !{i32 [[@LINE+1]], i32 0, metadata !{{.*}}, null} +} -- 2.40.0