summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGCall.cpp7
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp6
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp28
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h11
4 files changed, 45 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 47f3c648409..4b6fe42fccf 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1625,7 +1625,8 @@ static bool checkThisPointer(llvm::Value *ThisArg, llvm::Value *This) {
return false;
}
-void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI) {
+void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
+ bool EmitRetDbgLoc) {
// Functions with no result always return void.
if (ReturnValue == 0) {
Builder.CreateRetVoid();
@@ -1670,8 +1671,10 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI) {
// If there is a dominating store to ReturnValue, we can elide
// the load, zap the store, and usually zap the alloca.
if (llvm::StoreInst *SI = findDominatingStoreToReturnValue(*this)) {
+ // Reuse the debug location from the store unless we're told not to.
+ if (EmitRetDbgLoc)
+ RetDbgLoc = SI->getDebugLoc();
// Get the stored value and nuke the now-dead store.
- RetDbgLoc = SI->getDebugLoc();
RV = SI->getValueOperand();
SI->eraseFromParent();
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index dcc423dbdc0..28bbc46c689 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -37,6 +37,9 @@ void CodeGenFunction::EmitStopPoint(const Stmt *S) {
else
Loc = S->getLocStart();
DI->EmitLocation(Builder, Loc);
+
+ if (++NumStopPoints == 1)
+ FirstStopPoint = Loc;
}
}
@@ -839,6 +842,9 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
}
}
+ if (RV == 0 || RV->isEvaluatable(getContext()))
+ ++NumSimpleReturnExprs;
+
cleanupScope.ForceCleanup();
EmitBranchThroughCleanup(ReturnBlock);
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 0daae58bdc7..122e95b2663 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -44,6 +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),
CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0),
CXXDefaultInitExprThis(0),
CXXStructorImplicitParamDecl(0), CXXStructorImplicitParamValue(0),
@@ -187,16 +188,35 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
assert(BreakContinueStack.empty() &&
"mismatched push/pop in break/continue stack!");
- if (CGDebugInfo *DI = getDebugInfo())
- DI->EmitLocation(Builder, EndLoc);
+ // 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 (CGDebugInfo *DI = getDebugInfo()) {
+ if (NumSimpleReturnExprs == 1 && NumStopPoints == 1)
+ DI->EmitLocation(Builder, FirstStopPoint);
+ else
+ DI->EmitLocation(Builder, EndLoc);
+ }
// Pop any cleanups that might have been associated with the
// parameters. Do this in whatever block we're currently in; it's
// important to do this before we enter the return block or return
// edges will be *really* confused.
- if (EHStack.stable_begin() != PrologueCleanupDepth)
+ bool EmitRetDbgLoc = true;
+ if (EHStack.stable_begin() != PrologueCleanupDepth) {
PopCleanupBlocks(PrologueCleanupDepth);
+ // 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)
+ DI->EmitLocation(Builder, EndLoc);
+ }
+
// Emit function epilog (to return).
EmitReturnBlock();
@@ -208,7 +228,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
DI->EmitFunctionEnd(Builder);
}
- EmitFunctionEpilog(*CurFnInfo);
+ EmitFunctionEpilog(*CurFnInfo, EmitRetDbgLoc);
EmitEndEHSpec(CurCodeDecl);
assert(EHStack.empty() &&
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 727a3be54b0..17df1dad3ef 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -1206,6 +1206,15 @@ private:
/// lazily by getUnreachableBlock().
llvm::BasicBlock *UnreachableBlock;
+ /// Counts of the number of distinct breakpoint locations in this function.
+ unsigned NumStopPoints;
+
+ /// Count the number of simple (constant) return expressions in the function.
+ unsigned NumSimpleReturnExprs;
+
+ /// The first debug location (breakpoint) in the function.
+ SourceLocation FirstStopPoint;
+
public:
/// A scope within which we are constructing the fields of an object which
/// might use a CXXDefaultInitExpr. This stashes away a 'this' value to use
@@ -1563,7 +1572,7 @@ public:
/// EmitFunctionEpilog - Emit the target specific LLVM code to return the
/// given temporary.
- void EmitFunctionEpilog(const CGFunctionInfo &FI);
+ void EmitFunctionEpilog(const CGFunctionInfo &FI, bool EmitRetDbgLoc);
/// EmitStartEHSpec - Emit the start of the exception spec.
void EmitStartEHSpec(const Decl *D);
OpenPOWER on IntegriCloud