@@ -70,47 +70,6 @@ class PrettyStackTraceRequest : public llvm::PrettyStackTraceEntry {
70
70
}
71
71
};
72
72
73
- // / An llvm::ErrorInfo container for a request in which a cycle was detected
74
- // / and diagnosed.
75
- template <typename Request>
76
- struct CyclicalRequestError :
77
- public llvm::ErrorInfo<CyclicalRequestError<Request>> {
78
- public:
79
- static char ID;
80
- const Request &request;
81
- const Evaluator &evaluator;
82
-
83
- CyclicalRequestError (const Request &request, const Evaluator &evaluator)
84
- : request(request), evaluator(evaluator) {}
85
-
86
- virtual void log (llvm::raw_ostream &out) const override ;
87
-
88
- virtual std::error_code convertToErrorCode () const override {
89
- // This is essentially unused, but is a temporary requirement for
90
- // llvm::ErrorInfo subclasses.
91
- llvm_unreachable (" shouldn't get std::error_code from CyclicalRequestError" );
92
- }
93
- };
94
-
95
- template <typename Request>
96
- char CyclicalRequestError<Request>::ID = ' \0 ' ;
97
-
98
- // / Evaluates a given request or returns a default value if a cycle is detected.
99
- template <typename Request>
100
- typename Request::OutputType
101
- evaluateOrDefault (
102
- Evaluator &eval, Request req, typename Request::OutputType def) {
103
- auto result = eval (req);
104
- if (auto err = result.takeError ()) {
105
- llvm::handleAllErrors (std::move (err),
106
- [](const CyclicalRequestError<Request> &E) {
107
- // cycle detected
108
- });
109
- return def;
110
- }
111
- return *result;
112
- }
113
-
114
73
// / Report that a request of the given kind is being evaluated, so it
115
74
// / can be recorded by the stats reporter.
116
75
template <typename Request>
@@ -256,37 +215,26 @@ class Evaluator {
256
215
257
216
// / Retrieve the result produced by evaluating a request that can
258
217
// / be cached.
259
- template <typename Request,
218
+ template <typename Request, typename Fn,
260
219
typename std::enable_if<Request::isEverCached>::type * = nullptr >
261
- llvm::Expected< typename Request::OutputType>
262
- operator ()(const Request &request) {
220
+ typename Request::OutputType
221
+ operator ()(const Request &request, Fn defaultValueFn ) {
263
222
// The request can be cached, but check a predicate to determine
264
223
// whether this particular instance is cached. This allows more
265
224
// fine-grained control over which instances get cache.
266
225
if (request.isCached ())
267
- return getResultCached (request);
226
+ return getResultCached (request, std::move (defaultValueFn) );
268
227
269
- return getResultUncached (request);
228
+ return getResultUncached (request, std::move (defaultValueFn) );
270
229
}
271
230
272
231
// / Retrieve the result produced by evaluating a request that
273
232
// / will never be cached.
274
- template <typename Request,
233
+ template <typename Request, typename Fn,
275
234
typename std::enable_if<!Request::isEverCached>::type * = nullptr >
276
- llvm::Expected<typename Request::OutputType>
277
- operator ()(const Request &request) {
278
- return getResultUncached (request);
279
- }
280
-
281
- // / Evaluate a set of requests and return their results as a tuple.
282
- // /
283
- // / Use this to describe cases where there are multiple (known)
284
- // / requests that all need to be satisfied.
285
- template <typename ...Requests>
286
- std::tuple<llvm::Expected<typename Requests::OutputType>...>
287
- operator ()(const Requests &...requests) {
288
- return std::tuple<llvm::Expected<typename Requests::OutputType>...>(
289
- (*this )(requests)...);
235
+ typename Request::OutputType
236
+ operator ()(const Request &request, Fn defaultValueFn) {
237
+ return getResultUncached (request, std::move (defaultValueFn));
290
238
}
291
239
292
240
// / Cache a precomputed value for the given request, so that it will not
@@ -304,7 +252,9 @@ class Evaluator {
304
252
typename std::enable_if<!Request::hasExternalCache>::type* = nullptr >
305
253
void cacheOutput (const Request &request,
306
254
typename Request::OutputType &&output) {
307
- cache.insert <Request>(request, std::move (output));
255
+ bool inserted = cache.insert <Request>(request, std::move (output));
256
+ assert (inserted && " Request result was already cached" );
257
+ (void ) inserted;
308
258
}
309
259
310
260
template <typename Request,
@@ -351,15 +301,14 @@ class Evaluator {
351
301
void finishedRequest (const ActiveRequest &request);
352
302
353
303
// / Produce the result of the request without caching.
354
- template <typename Request>
355
- llvm::Expected< typename Request::OutputType>
356
- getResultUncached (const Request &request) {
304
+ template <typename Request, typename Fn >
305
+ typename Request::OutputType
306
+ getResultUncached (const Request &request, Fn defaultValueFn ) {
357
307
auto activeReq = ActiveRequest (request);
358
308
359
309
// Check for a cycle.
360
310
if (checkDependency (activeReq)) {
361
- return llvm::Error (
362
- std::make_unique<CyclicalRequestError<Request>>(request, *this ));
311
+ return defaultValueFn ();
363
312
}
364
313
365
314
PrettyStackTraceRequest<Request> prettyStackTrace (request);
@@ -370,7 +319,7 @@ class Evaluator {
370
319
371
320
recorder.beginRequest <Request>();
372
321
373
- auto && result = getRequestFunction<Request>()(request, *this );
322
+ auto result = getRequestFunction<Request>()(request, *this );
374
323
375
324
recorder.endRequest <Request>(request);
376
325
@@ -381,16 +330,16 @@ class Evaluator {
381
330
// done.
382
331
finishedRequest (activeReq);
383
332
384
- return std::move ( result) ;
333
+ return result;
385
334
}
386
335
387
336
// / Get the result of a request, consulting an external cache
388
337
// / provided by the request to retrieve previously-computed results
389
338
// / and detect recursion.
390
- template <typename Request,
339
+ template <typename Request, typename Fn,
391
340
typename std::enable_if<Request::hasExternalCache>::type * = nullptr >
392
- llvm::Expected< typename Request::OutputType>
393
- getResultCached (const Request &request) {
341
+ typename Request::OutputType
342
+ getResultCached (const Request &request, Fn defaultValueFn ) {
394
343
// If there is a cached result, return it.
395
344
if (auto cached = request.getCachedResult ()) {
396
345
recorder.replayCachedRequest (request);
@@ -399,13 +348,10 @@ class Evaluator {
399
348
}
400
349
401
350
// Compute the result.
402
- auto result = getResultUncached (request);
351
+ auto result = getResultUncached (request, std::move (defaultValueFn) );
403
352
404
353
// Cache the result if applicable.
405
- if (!result)
406
- return result;
407
-
408
- request.cacheResult (*result);
354
+ request.cacheResult (result);
409
355
410
356
// Return it.
411
357
return result;
@@ -414,10 +360,10 @@ class Evaluator {
414
360
// / Get the result of a request, consulting the general cache to
415
361
// / retrieve previously-computed results and detect recursion.
416
362
template <
417
- typename Request,
363
+ typename Request, typename Fn,
418
364
typename std::enable_if<!Request::hasExternalCache>::type * = nullptr >
419
- llvm::Expected< typename Request::OutputType>
420
- getResultCached (const Request &request) {
365
+ typename Request::OutputType
366
+ getResultCached (const Request &request, Fn defaultValueFn ) {
421
367
// If we already have an entry for this request in the cache, return it.
422
368
auto known = cache.find_as <Request>(request);
423
369
if (known != cache.end <Request>()) {
@@ -428,12 +374,10 @@ class Evaluator {
428
374
}
429
375
430
376
// Compute the result.
431
- auto result = getResultUncached (request);
432
- if (!result)
433
- return result;
377
+ auto result = getResultUncached (request, std::move (defaultValueFn));
434
378
435
379
// Cache the result.
436
- cache.insert <Request>(request, * result);
380
+ cache.insert <Request>(request, result);
437
381
return result;
438
382
}
439
383
@@ -465,11 +409,20 @@ class Evaluator {
465
409
}
466
410
};
467
411
468
- template <typename Request>
469
- void CyclicalRequestError<Request>::log(llvm::raw_ostream &out) const {
470
- out << " Cycle detected:\n " ;
471
- simple_display (out, request);
472
- out << " \n " ;
412
+ // / Evaluates a given request or returns a default value if a cycle is detected.
413
+ template <typename Request>
414
+ typename Request::OutputType
415
+ evaluateOrDefault (Evaluator &eval, Request req, typename Request::OutputType def) {
416
+ return eval (req, [def]() { return def; });
417
+ }
418
+
419
+ // / Evaluates a given request or returns a default value if a cycle is detected.
420
+ template <typename Request>
421
+ typename Request::OutputType
422
+ evaluateOrFatal (Evaluator &eval, Request req) {
423
+ return eval (req, []() -> typename Request::OutputType {
424
+ llvm::report_fatal_error (" Request cycle" );
425
+ });
473
426
}
474
427
475
428
} // end namespace evaluator
0 commit comments