Skip to content

Commit 5b032bf

Browse files
committed
Implement more descriptive pretty stack printing for generated derivatives.
1 parent ec8c4a2 commit 5b032bf

7 files changed

Lines changed: 103 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/ReverseModeVisitor.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,13 @@ namespace clad {
108108
return m_Stack.top();
109109
}
110110
StmtDiff Visit(const clang::Stmt* stmt, clang::Expr* dfdS = nullptr) {
111+
m_CurVisitedStmt = stmt;
112+
#ifndef NDEBUG
113+
// Enable testing of the pretty printing of the state when clad crashes.
114+
if (const char* Env = std::getenv("CLAD_FORCE_CRASH"))
115+
std::terminate();
116+
#endif // NDEBUG
117+
111118
// No need to push the same expr multiple times.
112119
bool push = !(!m_Stack.empty() && (dfdS == dfdx()));
113120
if (push)

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"
@@ -64,6 +65,9 @@ DerivativeAndOverload BaseForwardModeVisitor::Derive() {
6465
assert(!m_DerivativeInFlight &&
6566
"Doesn't support recursive diff. Use DiffPlan.");
6667

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

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"
@@ -235,6 +236,10 @@ Expr* ReverseModeVisitor::getStdInitListSizeExpr(const Expr* E) {
235236

236237
DerivativeAndOverload ReverseModeVisitor::Derive() {
237238
assert(m_DiffReq.Function && "Must not be null.");
239+
240+
PrettyStackTraceDerivative CrashInfo(m_DiffReq, m_Blocks, m_Sema,
241+
&m_CurVisitedStmt);
242+
238243
if (m_ExternalSource)
239244
m_ExternalSource->ActOnStartOfDerive();
240245
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: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: env CLAD_FORCE_CRASH= not %cladclang %s -I%S/../../include 2>&1 | FileCheck %s
2+
// RUN: env CLAD_FORCE_CRASH= not %cladclang -DREVERSE %s -I%S/../../include 2>&1 | FileCheck %s
3+
// REQUIRES: asserts
4+
5+
#include "clad/Differentiator/Differentiator.h"
6+
7+
double fn1(double x) {
8+
return x * x + 3 * x + 5;
9+
}
10+
11+
int main() {
12+
#ifdef REVERSE
13+
auto grad = clad::gradient(fn1);
14+
#else
15+
auto dx = clad::differentiate(fn1);
16+
#endif
17+
}
18+
19+
// CHECK: Building code for '<double fn1(double x)>[name=fn1, order=1, mode={{.*}}, args='', tbr]'
20+
// CHECK-NEXT: While visiting <CompoundStmt> [ '
21+
// CHECK: --- Begin Stmt Dump ---
22+
// CHECK return x * x + 3 * x + 5;
23+
// CHECK: --- End Stmt Dump ---

0 commit comments

Comments
 (0)