@@ -70,47 +70,6 @@ class PrettyStackTraceRequest : public llvm::PrettyStackTraceEntry {
7070 }
7171};
7272
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-
11473// / Report that a request of the given kind is being evaluated, so it
11574// / can be recorded by the stats reporter.
11675template <typename Request>
@@ -256,37 +215,26 @@ class Evaluator {
256215
257216 // / Retrieve the result produced by evaluating a request that can
258217 // / be cached.
259- template <typename Request,
218+ template <typename Request, typename Fn,
260219 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 ) {
263222 // The request can be cached, but check a predicate to determine
264223 // whether this particular instance is cached. This allows more
265224 // fine-grained control over which instances get cache.
266225 if (request.isCached ())
267- return getResultCached (request);
226+ return getResultCached (request, std::move (defaultValueFn) );
268227
269- return getResultUncached (request);
228+ return getResultUncached (request, std::move (defaultValueFn) );
270229 }
271230
272231 // / Retrieve the result produced by evaluating a request that
273232 // / will never be cached.
274- template <typename Request,
233+ template <typename Request, typename Fn,
275234 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));
290238 }
291239
292240 // / Cache a precomputed value for the given request, so that it will not
@@ -304,7 +252,9 @@ class Evaluator {
304252 typename std::enable_if<!Request::hasExternalCache>::type* = nullptr >
305253 void cacheOutput (const Request &request,
306254 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;
308258 }
309259
310260 template <typename Request,
@@ -351,15 +301,14 @@ class Evaluator {
351301 void finishedRequest (const ActiveRequest &request);
352302
353303 // / 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 ) {
357307 auto activeReq = ActiveRequest (request);
358308
359309 // Check for a cycle.
360310 if (checkDependency (activeReq)) {
361- return llvm::Error (
362- std::make_unique<CyclicalRequestError<Request>>(request, *this ));
311+ return defaultValueFn ();
363312 }
364313
365314 PrettyStackTraceRequest<Request> prettyStackTrace (request);
@@ -370,7 +319,7 @@ class Evaluator {
370319
371320 recorder.beginRequest <Request>();
372321
373- auto && result = getRequestFunction<Request>()(request, *this );
322+ auto result = getRequestFunction<Request>()(request, *this );
374323
375324 recorder.endRequest <Request>(request);
376325
@@ -381,16 +330,16 @@ class Evaluator {
381330 // done.
382331 finishedRequest (activeReq);
383332
384- return std::move ( result) ;
333+ return result;
385334 }
386335
387336 // / Get the result of a request, consulting an external cache
388337 // / provided by the request to retrieve previously-computed results
389338 // / and detect recursion.
390- template <typename Request,
339+ template <typename Request, typename Fn,
391340 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 ) {
394343 // If there is a cached result, return it.
395344 if (auto cached = request.getCachedResult ()) {
396345 recorder.replayCachedRequest (request);
@@ -399,13 +348,10 @@ class Evaluator {
399348 }
400349
401350 // Compute the result.
402- auto result = getResultUncached (request);
351+ auto result = getResultUncached (request, std::move (defaultValueFn) );
403352
404353 // Cache the result if applicable.
405- if (!result)
406- return result;
407-
408- request.cacheResult (*result);
354+ request.cacheResult (result);
409355
410356 // Return it.
411357 return result;
@@ -414,10 +360,10 @@ class Evaluator {
414360 // / Get the result of a request, consulting the general cache to
415361 // / retrieve previously-computed results and detect recursion.
416362 template <
417- typename Request,
363+ typename Request, typename Fn,
418364 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 ) {
421367 // If we already have an entry for this request in the cache, return it.
422368 auto known = cache.find_as <Request>(request);
423369 if (known != cache.end <Request>()) {
@@ -428,12 +374,10 @@ class Evaluator {
428374 }
429375
430376 // Compute the result.
431- auto result = getResultUncached (request);
432- if (!result)
433- return result;
377+ auto result = getResultUncached (request, std::move (defaultValueFn));
434378
435379 // Cache the result.
436- cache.insert <Request>(request, * result);
380+ cache.insert <Request>(request, result);
437381 return result;
438382 }
439383
@@ -465,11 +409,20 @@ class Evaluator {
465409 }
466410};
467411
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+ });
473426}
474427
475428} // end namespace evaluator
0 commit comments