Skip to content

Commit fa0387b

Browse files
committed
Implement more descriptive pretty stack printing for generated derivatives.
1 parent a81370d commit fa0387b

6 files changed

Lines changed: 91 additions & 0 deletions

File tree

include/clad/Differentiator/BaseForwardModeVisitor.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ class BaseForwardModeVisitor
3939
///
4040
DerivativeAndOverload Derive() override;
4141

42+
StmtDiff Visit(const clang::Stmt* S) {
43+
m_CurVisitedStmt = S;
44+
#ifndef NDEBUG
45+
// Enable testing of the pretty printing of the state when clad crashes.
46+
if (const char* Env = std::getenv("CLAD_FORCE_CRASH"))
47+
std::terminate();
48+
#endif // NDEBUG
49+
return clang::ConstStmtVisitor<BaseForwardModeVisitor, StmtDiff>::Visit(S);
50+
}
51+
4252
virtual void ExecuteInsidePushforwardFunctionBlock() {}
4353

4454
virtual StmtDiff

include/clad/Differentiator/VisitorBase.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "clang/Sema/Sema.h"
2121
#include "llvm/ADT/ArrayRef.h"
2222
#include "llvm/ADT/StringRef.h"
23+
#include "llvm/Support/PrettyStackTrace.h"
2324

2425
#include <array>
2526
#include <stack>
@@ -29,6 +30,10 @@ namespace clang {
2930
class NestedNameSpecifier;
3031
} // namespace clang
3132

33+
namespace llvm {
34+
class raw_ostream;
35+
} // namespace llvm
36+
3237
namespace clad {
3338
class MultiplexExternalRMVSource;
3439
/// A class that represents the result of Visit of ForwardModeVisitor.
@@ -136,6 +141,9 @@ namespace clad {
136141
// expression to be of object type in the reverse mode as well.
137142
clang::Expr* m_ThisExprDerivative = nullptr;
138143

144+
/// The currently visited statement. Useful for crash pretty-printing.
145+
const clang::Stmt* m_CurVisitedStmt = nullptr;
146+
139147
/// A function used to wrap result of visiting E in a lambda. Returns a call
140148
/// to the built lambda. Func is a functor that will be invoked inside
141149
/// lambda scope and block. Statements inside lambda are expected to be
@@ -671,6 +679,23 @@ namespace clad {
671679
clang::TemplateDecl* m_CladConstructorPushforwardTag = nullptr;
672680
clang::TemplateDecl* m_CladConstructorReverseForwTag = nullptr;
673681
};
682+
683+
/// A class that generates prettier stack traces when we crash on generating
684+
/// a derivative.
685+
class PrettyStackTraceDerivative : public llvm::PrettyStackTraceEntry {
686+
const DiffRequest& m_DiffReq;
687+
using Blocks = std::vector<llvm::SmallVector<clang::Stmt*, 16>>;
688+
const Blocks& m_Blocks;
689+
const clang::Sema& m_Sema;
690+
const clang::Stmt** m_Stmt = nullptr;
691+
692+
public:
693+
PrettyStackTraceDerivative(const DiffRequest& DiffReq, const Blocks& B,
694+
const clang::Sema& Sema, const clang::Stmt** S)
695+
: m_DiffReq(DiffReq), m_Blocks(B), m_Sema(Sema), m_Stmt(S) {}
696+
void print(llvm::raw_ostream& OS) const override;
697+
};
698+
674699
} // end namespace clad
675700

676701
#endif // CLAD_VISITOR_BASE_H

lib/Differentiator/BaseForwardModeVisitor.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "clad/Differentiator/DiffPlanner.h"
1414
#include "clad/Differentiator/ErrorEstimator.h"
1515
#include "clad/Differentiator/ParseDiffArgsTypes.h"
16+
#include "clad/Differentiator/VisitorBase.h"
1617

1718
#include "clang/AST/ASTContext.h"
1819
#include "clang/AST/ASTLambda.h"
@@ -63,6 +64,9 @@ DerivativeAndOverload BaseForwardModeVisitor::Derive() {
6364
assert(!m_DerivativeInFlight &&
6465
"Doesn't support recursive diff. Use DiffPlan.");
6566

67+
PrettyStackTraceDerivative CrashInfo(m_DiffReq, m_Blocks, m_Sema,
68+
&m_CurVisitedStmt);
69+
6670
llvm::SaveAndRestore<bool> saveInFlight(m_DerivativeInFlight,
6771
/*NewValue=*/true);
6872

lib/Differentiator/ReverseModeVisitor.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "clad/Differentiator/ExternalRMVSource.h"
1616
#include "clad/Differentiator/MultiplexExternalRMVSource.h"
1717
#include "clad/Differentiator/StmtClone.h"
18+
#include "clad/Differentiator/VisitorBase.h"
1819

1920
#include "clang/AST/ASTContext.h"
2021
#include "clang/AST/ASTLambda.h"
@@ -234,6 +235,10 @@ Expr* ReverseModeVisitor::getStdInitListSizeExpr(const Expr* E) {
234235

235236
DerivativeAndOverload ReverseModeVisitor::Derive() {
236237
assert(m_DiffReq.Function && "Must not be null.");
238+
239+
PrettyStackTraceDerivative CrashInfo(m_DiffReq, m_Blocks, m_Sema,
240+
&m_CurVisitedStmt);
241+
237242
if (m_ExternalSource)
238243
m_ExternalSource->ActOnStartOfDerive();
239244
if (m_DiffReq.Mode == DiffMode::error_estimation)

lib/Differentiator/VisitorBase.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "clang/AST/NestedNameSpecifier.h"
2323
#include "clang/AST/TemplateBase.h"
2424
#include "clang/Basic/OperatorKinds.h"
25+
#include "clang/Basic/SourceManager.h"
2526
#include "clang/Lex/Preprocessor.h"
2627
#include "clang/Sema/Lookup.h"
2728
#include "clang/Sema/Overload.h"
@@ -1072,4 +1073,32 @@ namespace clad {
10721073
}
10731074
return nullptr;
10741075
}
1076+
1077+
void PrettyStackTraceDerivative::print(llvm::raw_ostream& OS) const {
1078+
OS << "Building code for '" << (std::string)m_DiffReq << "'\n";
1079+
clang::PrintingPolicy P(m_Sema.getASTContext().getLangOpts());
1080+
if (m_Stmt) {
1081+
const Stmt* S = *m_Stmt;
1082+
clang::SourceLocation B = S->getBeginLoc();
1083+
clang::SourceLocation E = S->getEndLoc();
1084+
clang::SourceManager& SM = m_Sema.getSourceManager();
1085+
1086+
OS << "While visiting <" << S->getStmtClassName() << ">"
1087+
<< " [ '";
1088+
B.print(OS, SM);
1089+
OS << "', '";
1090+
E.print(OS, SM);
1091+
OS << "']\n";
1092+
1093+
OS << "\n--- Begin Stmt Dump ---\n";
1094+
(*m_Stmt)->printPretty(OS, /*Helper=*/nullptr, P);
1095+
OS << "\n--- End Stmt Dump ---\n";
1096+
}
1097+
1098+
if (!m_Blocks.empty() && !m_Blocks.back().empty()) {
1099+
OS << "Last forward statement ";
1100+
m_Blocks.back().back()->printPretty(OS, /*Helper=*/nullptr, P);
1101+
}
1102+
}
1103+
10751104
} // end namespace clad

test/Misc/CrashDiags.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: env CLAD_FORCE_CRASH= not %cladclang %s -I%S/../../include 2>&1 | FileCheck %s
2+
// REQUIRES: asserts
3+
4+
#include "clad/Differentiator/Differentiator.h"
5+
6+
double fn1(double x) {
7+
return x * x + 3 * x + 5;
8+
}
9+
10+
int main() {
11+
auto grad = clad::differentiate(fn1);
12+
}
13+
14+
// CHECK: Building code for '<double fn1(double x)>[name=fn1, order=1, mode=forward, args='', tbr]'
15+
// CHECK-NEXT: While visiting <CompoundStmt> [ '
16+
// CHECK: --- Begin Stmt Dump ---
17+
// CHECK return x * x + 3 * x + 5;
18+
// CHECK: --- End Stmt Dump ---

0 commit comments

Comments
 (0)