@@ -38,7 +38,7 @@ namespace detail {
38
38
// / reproducers when a signal is raised, such as a segfault.
39
39
struct RecoveryReproducerContext {
40
40
RecoveryReproducerContext (std::string passPipelineStr, Operation *op,
41
- PassManager:: ReproducerStreamFactory &streamFactory,
41
+ ReproducerStreamFactory &streamFactory,
42
42
bool verifyPasses);
43
43
~RecoveryReproducerContext ();
44
44
@@ -67,7 +67,7 @@ struct RecoveryReproducerContext {
67
67
68
68
// / The factory for the reproducer output stream to use when generating the
69
69
// / reproducer.
70
- PassManager:: ReproducerStreamFactory &streamFactory;
70
+ ReproducerStreamFactory &streamFactory;
71
71
72
72
// / Various pass manager and context flags.
73
73
bool disableThreads;
@@ -92,7 +92,7 @@ llvm::ManagedStatic<llvm::SmallSetVector<RecoveryReproducerContext *, 1>>
92
92
93
93
RecoveryReproducerContext::RecoveryReproducerContext (
94
94
std::string passPipelineStr, Operation *op,
95
- PassManager:: ReproducerStreamFactory &streamFactory, bool verifyPasses)
95
+ ReproducerStreamFactory &streamFactory, bool verifyPasses)
96
96
: pipelineElements(std::move(passPipelineStr)),
97
97
preCrashOperation(op->clone ()), streamFactory(streamFactory),
98
98
disableThreads(!op->getContext ()->isMultithreadingEnabled()),
@@ -106,22 +106,24 @@ RecoveryReproducerContext::~RecoveryReproducerContext() {
106
106
disable ();
107
107
}
108
108
109
- void RecoveryReproducerContext::generate (std::string &description) {
109
+ static void appendReproducer (std::string &description, Operation *op,
110
+ const ReproducerStreamFactory &factory,
111
+ const std::string &pipelineElements,
112
+ bool disableThreads, bool verifyPasses) {
110
113
llvm::raw_string_ostream descOS (description);
111
114
112
115
// Try to create a new output stream for this crash reproducer.
113
116
std::string error;
114
- std::unique_ptr<PassManager:: ReproducerStream> stream = streamFactory (error);
117
+ std::unique_ptr<ReproducerStream> stream = factory (error);
115
118
if (!stream) {
116
119
descOS << " failed to create output stream: " << error;
117
120
return ;
118
121
}
119
122
descOS << " reproducer generated at `" << stream->description () << " `" ;
120
123
121
- std::string pipeline = (preCrashOperation->getName ().getStringRef () + " (" +
122
- pipelineElements + " )" )
123
- .str ();
124
- AsmState state (preCrashOperation);
124
+ std::string pipeline =
125
+ (op->getName ().getStringRef () + " (" + pipelineElements + " )" ).str ();
126
+ AsmState state (op);
125
127
state.attachResourcePrinter (
126
128
" mlir_reproducer" , [&](Operation *op, AsmResourceBuilder &builder) {
127
129
builder.buildString (" pipeline" , pipeline);
@@ -130,7 +132,12 @@ void RecoveryReproducerContext::generate(std::string &description) {
130
132
});
131
133
132
134
// Output the .mlir module.
133
- preCrashOperation->print (stream->os (), state);
135
+ op->print (stream->os (), state);
136
+ }
137
+
138
+ void RecoveryReproducerContext::generate (std::string &description) {
139
+ appendReproducer (description, preCrashOperation, streamFactory,
140
+ pipelineElements, disableThreads, verifyPasses);
134
141
}
135
142
136
143
void RecoveryReproducerContext::disable () {
@@ -175,12 +182,11 @@ void RecoveryReproducerContext::registerSignalHandler() {
175
182
// ===----------------------------------------------------------------------===//
176
183
177
184
struct PassCrashReproducerGenerator ::Impl {
178
- Impl (PassManager::ReproducerStreamFactory &streamFactory,
179
- bool localReproducer)
185
+ Impl (ReproducerStreamFactory &streamFactory, bool localReproducer)
180
186
: streamFactory(streamFactory), localReproducer(localReproducer) {}
181
187
182
188
// / The factory to use when generating a crash reproducer.
183
- PassManager:: ReproducerStreamFactory streamFactory;
189
+ ReproducerStreamFactory streamFactory;
184
190
185
191
// / Flag indicating if reproducer generation should be localized to the
186
192
// / failing pass.
@@ -198,7 +204,7 @@ struct PassCrashReproducerGenerator::Impl {
198
204
};
199
205
200
206
PassCrashReproducerGenerator::PassCrashReproducerGenerator (
201
- PassManager:: ReproducerStreamFactory &streamFactory, bool localReproducer)
207
+ ReproducerStreamFactory &streamFactory, bool localReproducer)
202
208
: impl(std::make_unique<Impl>(streamFactory, localReproducer)) {}
203
209
PassCrashReproducerGenerator::~PassCrashReproducerGenerator () = default ;
204
210
@@ -382,9 +388,9 @@ struct CrashReproducerInstrumentation : public PassInstrumentation {
382
388
// ===----------------------------------------------------------------------===//
383
389
384
390
namespace {
385
- // / This class represents a default instance of PassManager ::ReproducerStream
391
+ // / This class represents a default instance of mlir ::ReproducerStream
386
392
// / that is backed by a file.
387
- struct FileReproducerStream : public PassManager ::ReproducerStream {
393
+ struct FileReproducerStream : public mlir ::ReproducerStream {
388
394
FileReproducerStream (std::unique_ptr<llvm::ToolOutputFile> outputFile)
389
395
: outputFile(std::move(outputFile)) {}
390
396
~FileReproducerStream () override { outputFile->keep (); }
@@ -418,22 +424,45 @@ LogicalResult PassManager::runWithCrashRecovery(Operation *op,
418
424
return passManagerResult;
419
425
}
420
426
421
- void PassManager::enableCrashReproducerGeneration (StringRef outputFile,
422
- bool genLocalReproducer ) {
427
+ static ReproducerStreamFactory
428
+ makeReproducerStreamFactory (StringRef outputFile ) {
423
429
// Capture the filename by value in case outputFile is out of scope when
424
430
// invoked.
425
431
std::string filename = outputFile.str ();
426
- enableCrashReproducerGeneration (
427
- [filename](std::string &error) -> std::unique_ptr<ReproducerStream> {
428
- std::unique_ptr<llvm::ToolOutputFile> outputFile =
429
- mlir::openOutputFile (filename, &error);
430
- if (!outputFile) {
431
- error = " Failed to create reproducer stream: " + error;
432
- return nullptr ;
433
- }
434
- return std::make_unique<FileReproducerStream>(std::move (outputFile));
435
- },
436
- genLocalReproducer);
432
+ return [filename](std::string &error) -> std::unique_ptr<ReproducerStream> {
433
+ std::unique_ptr<llvm::ToolOutputFile> outputFile =
434
+ mlir::openOutputFile (filename, &error);
435
+ if (!outputFile) {
436
+ error = " Failed to create reproducer stream: " + error;
437
+ return nullptr ;
438
+ }
439
+ return std::make_unique<FileReproducerStream>(std::move (outputFile));
440
+ };
441
+ }
442
+
443
+ void printAsTextualPipeline (
444
+ raw_ostream &os, StringRef anchorName,
445
+ const llvm::iterator_range<OpPassManager::pass_iterator> &passes);
446
+
447
+ std::string mlir::makeReproducer (
448
+ StringRef anchorName,
449
+ const llvm::iterator_range<OpPassManager::pass_iterator> &passes,
450
+ Operation *op, StringRef outputFile, bool disableThreads,
451
+ bool verifyPasses) {
452
+
453
+ std::string description;
454
+ std::string pipelineStr;
455
+ llvm::raw_string_ostream passOS (pipelineStr);
456
+ ::printAsTextualPipeline (passOS, anchorName, passes);
457
+ appendReproducer (description, op, makeReproducerStreamFactory (outputFile),
458
+ pipelineStr, disableThreads, verifyPasses);
459
+ return description;
460
+ }
461
+
462
+ void PassManager::enableCrashReproducerGeneration (StringRef outputFile,
463
+ bool genLocalReproducer) {
464
+ enableCrashReproducerGeneration (makeReproducerStreamFactory (outputFile),
465
+ genLocalReproducer);
437
466
}
438
467
439
468
void PassManager::enableCrashReproducerGeneration (
0 commit comments