Bug Summary

File:tools/lli/ChildTarget/ChildTarget.cpp
Warning:line 1151, column 14
1st function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ChildTarget.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn326061/build-llvm/tools/lli/ChildTarget -I /build/llvm-toolchain-snapshot-7~svn326061/tools/lli/ChildTarget -I /build/llvm-toolchain-snapshot-7~svn326061/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn326061/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn326061/build-llvm/tools/lli/ChildTarget -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-02-26-041543-15277-1 -x c++ /build/llvm-toolchain-snapshot-7~svn326061/tools/lli/ChildTarget/ChildTarget.cpp

/build/llvm-toolchain-snapshot-7~svn326061/tools/lli/ChildTarget/ChildTarget.cpp

1#include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
2#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h"
3#include "llvm/Support/Debug.h"
4#include "llvm/Support/DynamicLibrary.h"
5#include "llvm/Support/Process.h"
6#include <sstream>
7
8#include "../RemoteJITUtils.h"
9
10using namespace llvm;
11using namespace llvm::orc;
12using namespace llvm::sys;
13
14#ifdef __x86_64__1
15typedef OrcX86_64_SysV HostOrcArch;
16#else
17typedef OrcGenericABI HostOrcArch;
18#endif
19
20ExitOnError ExitOnErr;
21
22int main(int argc, char *argv[]) {
23
24 if (argc != 3) {
1
Assuming 'argc' is equal to 3
2
Taking false branch
25 errs() << "Usage: " << argv[0] << " <input fd> <output fd>\n";
26 return 1;
27 }
28
29 ExitOnErr.setBanner(std::string(argv[0]) + ":");
30
31 int InFD;
32 int OutFD;
33 {
34 std::istringstream InFDStream(argv[1]), OutFDStream(argv[2]);
35 InFDStream >> InFD;
36 OutFDStream >> OutFD;
37 }
38
39 if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) {
3
Taking false branch
40 errs() << "Error loading program symbols.\n";
41 return 1;
42 }
43
44 auto SymbolLookup = [](const std::string &Name) {
45 return RTDyldMemoryManager::getSymbolAddressInProcess(Name);
46 };
47
48 auto RegisterEHFrames = [](uint8_t *Addr, uint32_t Size) {
49 RTDyldMemoryManager::registerEHFramesInProcess(Addr, Size);
50 };
51
52 auto DeregisterEHFrames = [](uint8_t *Addr, uint32_t Size) {
53 RTDyldMemoryManager::deregisterEHFramesInProcess(Addr, Size);
54 };
55
56 FDRawChannel Channel(InFD, OutFD);
57 typedef remote::OrcRemoteTargetServer<FDRawChannel, HostOrcArch> JITServer;
58 JITServer Server(Channel, SymbolLookup, RegisterEHFrames, DeregisterEHFrames);
59
60 while (!Server.receivedTerminate())
4
Assuming the condition is true
5
Loop condition is true. Entering loop body
61 ExitOnErr(Server.handleOne());
6
Calling 'RPCEndpointBase::handleOne'
62
63 close(InFD);
64 close(OutFD);
65
66 return 0;
67}

/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h

1//===------- RPCUTils.h - Utilities for building RPC APIs -------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Utilities to support construction of simple RPC APIs.
11//
12// The RPC utilities aim for ease of use (minimal conceptual overhead) for C++
13// programmers, high performance, low memory overhead, and efficient use of the
14// communications channel.
15//
16//===----------------------------------------------------------------------===//
17
18#ifndef LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H
19#define LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H
20
21#include <map>
22#include <thread>
23#include <vector>
24
25#include "llvm/ADT/STLExtras.h"
26#include "llvm/ExecutionEngine/Orc/OrcError.h"
27#include "llvm/ExecutionEngine/Orc/RPCSerialization.h"
28
29#include <future>
30
31namespace llvm {
32namespace orc {
33namespace rpc {
34
35/// Base class of all fatal RPC errors (those that necessarily result in the
36/// termination of the RPC session).
37class RPCFatalError : public ErrorInfo<RPCFatalError> {
38public:
39 static char ID;
40};
41
42/// RPCConnectionClosed is returned from RPC operations if the RPC connection
43/// has already been closed due to either an error or graceful disconnection.
44class ConnectionClosed : public ErrorInfo<ConnectionClosed> {
45public:
46 static char ID;
47 std::error_code convertToErrorCode() const override;
48 void log(raw_ostream &OS) const override;
49};
50
51/// BadFunctionCall is returned from handleOne when the remote makes a call with
52/// an unrecognized function id.
53///
54/// This error is fatal because Orc RPC needs to know how to parse a function
55/// call to know where the next call starts, and if it doesn't recognize the
56/// function id it cannot parse the call.
57template <typename FnIdT, typename SeqNoT>
58class BadFunctionCall
59 : public ErrorInfo<BadFunctionCall<FnIdT, SeqNoT>, RPCFatalError> {
60public:
61 static char ID;
62
63 BadFunctionCall(FnIdT FnId, SeqNoT SeqNo)
64 : FnId(std::move(FnId)), SeqNo(std::move(SeqNo)) {}
65
66 std::error_code convertToErrorCode() const override {
67 return orcError(OrcErrorCode::UnexpectedRPCCall);
68 }
69
70 void log(raw_ostream &OS) const override {
71 OS << "Call to invalid RPC function id '" << FnId << "' with "
72 "sequence number " << SeqNo;
73 }
74
75private:
76 FnIdT FnId;
77 SeqNoT SeqNo;
78};
79
80template <typename FnIdT, typename SeqNoT>
81char BadFunctionCall<FnIdT, SeqNoT>::ID = 0;
82
83/// InvalidSequenceNumberForResponse is returned from handleOne when a response
84/// call arrives with a sequence number that doesn't correspond to any in-flight
85/// function call.
86///
87/// This error is fatal because Orc RPC needs to know how to parse the rest of
88/// the response call to know where the next call starts, and if it doesn't have
89/// a result parser for this sequence number it can't do that.
90template <typename SeqNoT>
91class InvalidSequenceNumberForResponse
92 : public ErrorInfo<InvalidSequenceNumberForResponse<SeqNoT>, RPCFatalError> {
93public:
94 static char ID;
95
96 InvalidSequenceNumberForResponse(SeqNoT SeqNo)
97 : SeqNo(std::move(SeqNo)) {}
98
99 std::error_code convertToErrorCode() const override {
100 return orcError(OrcErrorCode::UnexpectedRPCCall);
101 };
102
103 void log(raw_ostream &OS) const override {
104 OS << "Response has unknown sequence number " << SeqNo;
105 }
106private:
107 SeqNoT SeqNo;
108};
109
110template <typename SeqNoT>
111char InvalidSequenceNumberForResponse<SeqNoT>::ID = 0;
112
113/// This non-fatal error will be passed to asynchronous result handlers in place
114/// of a result if the connection goes down before a result returns, or if the
115/// function to be called cannot be negotiated with the remote.
116class ResponseAbandoned : public ErrorInfo<ResponseAbandoned> {
117public:
118 static char ID;
119
120 std::error_code convertToErrorCode() const override;
121 void log(raw_ostream &OS) const override;
122};
123
124/// This error is returned if the remote does not have a handler installed for
125/// the given RPC function.
126class CouldNotNegotiate : public ErrorInfo<CouldNotNegotiate> {
127public:
128 static char ID;
129
130 CouldNotNegotiate(std::string Signature);
131 std::error_code convertToErrorCode() const override;
132 void log(raw_ostream &OS) const override;
133 const std::string &getSignature() const { return Signature; }
134private:
135 std::string Signature;
136};
137
138template <typename DerivedFunc, typename FnT> class Function;
139
140// RPC Function class.
141// DerivedFunc should be a user defined class with a static 'getName()' method
142// returning a const char* representing the function's name.
143template <typename DerivedFunc, typename RetT, typename... ArgTs>
144class Function<DerivedFunc, RetT(ArgTs...)> {
145public:
146 /// User defined function type.
147 using Type = RetT(ArgTs...);
148
149 /// Return type.
150 using ReturnType = RetT;
151
152 /// Returns the full function prototype as a string.
153 static const char *getPrototype() {
154 std::lock_guard<std::mutex> Lock(NameMutex);
155 if (Name.empty())
156 raw_string_ostream(Name)
157 << RPCTypeName<RetT>::getName() << " " << DerivedFunc::getName()
158 << "(" << llvm::orc::rpc::RPCTypeNameSequence<ArgTs...>() << ")";
159 return Name.data();
160 }
161
162private:
163 static std::mutex NameMutex;
164 static std::string Name;
165};
166
167template <typename DerivedFunc, typename RetT, typename... ArgTs>
168std::mutex Function<DerivedFunc, RetT(ArgTs...)>::NameMutex;
169
170template <typename DerivedFunc, typename RetT, typename... ArgTs>
171std::string Function<DerivedFunc, RetT(ArgTs...)>::Name;
172
173/// Allocates RPC function ids during autonegotiation.
174/// Specializations of this class must provide four members:
175///
176/// static T getInvalidId():
177/// Should return a reserved id that will be used to represent missing
178/// functions during autonegotiation.
179///
180/// static T getResponseId():
181/// Should return a reserved id that will be used to send function responses
182/// (return values).
183///
184/// static T getNegotiateId():
185/// Should return a reserved id for the negotiate function, which will be used
186/// to negotiate ids for user defined functions.
187///
188/// template <typename Func> T allocate():
189/// Allocate a unique id for function Func.
190template <typename T, typename = void> class RPCFunctionIdAllocator;
191
192/// This specialization of RPCFunctionIdAllocator provides a default
193/// implementation for integral types.
194template <typename T>
195class RPCFunctionIdAllocator<
196 T, typename std::enable_if<std::is_integral<T>::value>::type> {
197public:
198 static T getInvalidId() { return T(0); }
199 static T getResponseId() { return T(1); }
200 static T getNegotiateId() { return T(2); }
201
202 template <typename Func> T allocate() { return NextId++; }
203
204private:
205 T NextId = 3;
206};
207
208namespace detail {
209
210// FIXME: Remove MSVCPError/MSVCPExpected once MSVC's future implementation
211// supports classes without default constructors.
212#ifdef _MSC_VER
213
214namespace msvc_hacks {
215
216// Work around MSVC's future implementation's use of default constructors:
217// A default constructed value in the promise will be overwritten when the
218// real error is set - so the default constructed Error has to be checked
219// already.
220class MSVCPError : public Error {
221public:
222 MSVCPError() { (void)!!*this; }
223
224 MSVCPError(MSVCPError &&Other) : Error(std::move(Other)) {}
225
226 MSVCPError &operator=(MSVCPError Other) {
227 Error::operator=(std::move(Other));
228 return *this;
229 }
230
231 MSVCPError(Error Err) : Error(std::move(Err)) {}
232};
233
234// Work around MSVC's future implementation, similar to MSVCPError.
235template <typename T> class MSVCPExpected : public Expected<T> {
236public:
237 MSVCPExpected()
238 : Expected<T>(make_error<StringError>("", inconvertibleErrorCode())) {
239 consumeError(this->takeError());
240 }
241
242 MSVCPExpected(MSVCPExpected &&Other) : Expected<T>(std::move(Other)) {}
243
244 MSVCPExpected &operator=(MSVCPExpected &&Other) {
245 Expected<T>::operator=(std::move(Other));
246 return *this;
247 }
248
249 MSVCPExpected(Error Err) : Expected<T>(std::move(Err)) {}
250
251 template <typename OtherT>
252 MSVCPExpected(
253 OtherT &&Val,
254 typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
255 nullptr)
256 : Expected<T>(std::move(Val)) {}
257
258 template <class OtherT>
259 MSVCPExpected(
260 Expected<OtherT> &&Other,
261 typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
262 nullptr)
263 : Expected<T>(std::move(Other)) {}
264
265 template <class OtherT>
266 explicit MSVCPExpected(
267 Expected<OtherT> &&Other,
268 typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
269 nullptr)
270 : Expected<T>(std::move(Other)) {}
271};
272
273} // end namespace msvc_hacks
274
275#endif // _MSC_VER
276
277/// Provides a typedef for a tuple containing the decayed argument types.
278template <typename T> class FunctionArgsTuple;
279
280template <typename RetT, typename... ArgTs>
281class FunctionArgsTuple<RetT(ArgTs...)> {
282public:
283 using Type = std::tuple<typename std::decay<
284 typename std::remove_reference<ArgTs>::type>::type...>;
285};
286
287// ResultTraits provides typedefs and utilities specific to the return type
288// of functions.
289template <typename RetT> class ResultTraits {
290public:
291 // The return type wrapped in llvm::Expected.
292 using ErrorReturnType = Expected<RetT>;
293
294#ifdef _MSC_VER
295 // The ErrorReturnType wrapped in a std::promise.
296 using ReturnPromiseType = std::promise<msvc_hacks::MSVCPExpected<RetT>>;
297
298 // The ErrorReturnType wrapped in a std::future.
299 using ReturnFutureType = std::future<msvc_hacks::MSVCPExpected<RetT>>;
300#else
301 // The ErrorReturnType wrapped in a std::promise.
302 using ReturnPromiseType = std::promise<ErrorReturnType>;
303
304 // The ErrorReturnType wrapped in a std::future.
305 using ReturnFutureType = std::future<ErrorReturnType>;
306#endif
307
308 // Create a 'blank' value of the ErrorReturnType, ready and safe to
309 // overwrite.
310 static ErrorReturnType createBlankErrorReturnValue() {
311 return ErrorReturnType(RetT());
312 }
313
314 // Consume an abandoned ErrorReturnType.
315 static void consumeAbandoned(ErrorReturnType RetOrErr) {
316 consumeError(RetOrErr.takeError());
317 }
318};
319
320// ResultTraits specialization for void functions.
321template <> class ResultTraits<void> {
322public:
323 // For void functions, ErrorReturnType is llvm::Error.
324 using ErrorReturnType = Error;
325
326#ifdef _MSC_VER
327 // The ErrorReturnType wrapped in a std::promise.
328 using ReturnPromiseType = std::promise<msvc_hacks::MSVCPError>;
329
330 // The ErrorReturnType wrapped in a std::future.
331 using ReturnFutureType = std::future<msvc_hacks::MSVCPError>;
332#else
333 // The ErrorReturnType wrapped in a std::promise.
334 using ReturnPromiseType = std::promise<ErrorReturnType>;
335
336 // The ErrorReturnType wrapped in a std::future.
337 using ReturnFutureType = std::future<ErrorReturnType>;
338#endif
339
340 // Create a 'blank' value of the ErrorReturnType, ready and safe to
341 // overwrite.
342 static ErrorReturnType createBlankErrorReturnValue() {
343 return ErrorReturnType::success();
344 }
345
346 // Consume an abandoned ErrorReturnType.
347 static void consumeAbandoned(ErrorReturnType Err) {
348 consumeError(std::move(Err));
349 }
350};
351
352// ResultTraits<Error> is equivalent to ResultTraits<void>. This allows
353// handlers for void RPC functions to return either void (in which case they
354// implicitly succeed) or Error (in which case their error return is
355// propagated). See usage in HandlerTraits::runHandlerHelper.
356template <> class ResultTraits<Error> : public ResultTraits<void> {};
357
358// ResultTraits<Expected<T>> is equivalent to ResultTraits<T>. This allows
359// handlers for RPC functions returning a T to return either a T (in which
360// case they implicitly succeed) or Expected<T> (in which case their error
361// return is propagated). See usage in HandlerTraits::runHandlerHelper.
362template <typename RetT>
363class ResultTraits<Expected<RetT>> : public ResultTraits<RetT> {};
364
365// Determines whether an RPC function's defined error return type supports
366// error return value.
367template <typename T>
368class SupportsErrorReturn {
369public:
370 static const bool value = false;
371};
372
373template <>
374class SupportsErrorReturn<Error> {
375public:
376 static const bool value = true;
377};
378
379template <typename T>
380class SupportsErrorReturn<Expected<T>> {
381public:
382 static const bool value = true;
383};
384
385// RespondHelper packages return values based on whether or not the declared
386// RPC function return type supports error returns.
387template <bool FuncSupportsErrorReturn>
388class RespondHelper;
389
390// RespondHelper specialization for functions that support error returns.
391template <>
392class RespondHelper<true> {
393public:
394
395 // Send Expected<T>.
396 template <typename WireRetT, typename HandlerRetT, typename ChannelT,
397 typename FunctionIdT, typename SequenceNumberT>
398 static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId,
399 SequenceNumberT SeqNo,
400 Expected<HandlerRetT> ResultOrErr) {
401 if (!ResultOrErr && ResultOrErr.template errorIsA<RPCFatalError>())
402 return ResultOrErr.takeError();
403
404 // Open the response message.
405 if (auto Err = C.startSendMessage(ResponseId, SeqNo))
406 return Err;
407
408 // Serialize the result.
409 if (auto Err =
410 SerializationTraits<ChannelT, WireRetT,
411 Expected<HandlerRetT>>::serialize(
412 C, std::move(ResultOrErr)))
413 return Err;
414
415 // Close the response message.
416 return C.endSendMessage();
417 }
418
419 template <typename ChannelT, typename FunctionIdT, typename SequenceNumberT>
420 static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId,
421 SequenceNumberT SeqNo, Error Err) {
422 if (Err && Err.isA<RPCFatalError>())
423 return Err;
424 if (auto Err2 = C.startSendMessage(ResponseId, SeqNo))
425 return Err2;
426 if (auto Err2 = serializeSeq(C, std::move(Err)))
427 return Err2;
428 return C.endSendMessage();
429 }
430
431};
432
433// RespondHelper specialization for functions that do not support error returns.
434template <>
435class RespondHelper<false> {
436public:
437
438 template <typename WireRetT, typename HandlerRetT, typename ChannelT,
439 typename FunctionIdT, typename SequenceNumberT>
440 static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId,
441 SequenceNumberT SeqNo,
442 Expected<HandlerRetT> ResultOrErr) {
443 if (auto Err = ResultOrErr.takeError())
444 return Err;
445
446 // Open the response message.
447 if (auto Err = C.startSendMessage(ResponseId, SeqNo))
448 return Err;
449
450 // Serialize the result.
451 if (auto Err =
452 SerializationTraits<ChannelT, WireRetT, HandlerRetT>::serialize(
453 C, *ResultOrErr))
454 return Err;
455
456 // Close the response message.
457 return C.endSendMessage();
458 }
459
460 template <typename ChannelT, typename FunctionIdT, typename SequenceNumberT>
461 static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId,
462 SequenceNumberT SeqNo, Error Err) {
463 if (Err)
464 return Err;
465 if (auto Err2 = C.startSendMessage(ResponseId, SeqNo))
466 return Err2;
467 return C.endSendMessage();
468 }
469
470};
471
472
473// Send a response of the given wire return type (WireRetT) over the
474// channel, with the given sequence number.
475template <typename WireRetT, typename HandlerRetT, typename ChannelT,
476 typename FunctionIdT, typename SequenceNumberT>
477Error respond(ChannelT &C, const FunctionIdT &ResponseId,
478 SequenceNumberT SeqNo, Expected<HandlerRetT> ResultOrErr) {
479 return RespondHelper<SupportsErrorReturn<WireRetT>::value>::
480 template sendResult<WireRetT>(C, ResponseId, SeqNo, std::move(ResultOrErr));
481}
482
483// Send an empty response message on the given channel to indicate that
484// the handler ran.
485template <typename WireRetT, typename ChannelT, typename FunctionIdT,
486 typename SequenceNumberT>
487Error respond(ChannelT &C, const FunctionIdT &ResponseId, SequenceNumberT SeqNo,
488 Error Err) {
489 return RespondHelper<SupportsErrorReturn<WireRetT>::value>::
490 sendResult(C, ResponseId, SeqNo, std::move(Err));
491}
492
493// Converts a given type to the equivalent error return type.
494template <typename T> class WrappedHandlerReturn {
495public:
496 using Type = Expected<T>;
497};
498
499template <typename T> class WrappedHandlerReturn<Expected<T>> {
500public:
501 using Type = Expected<T>;
502};
503
504template <> class WrappedHandlerReturn<void> {
505public:
506 using Type = Error;
507};
508
509template <> class WrappedHandlerReturn<Error> {
510public:
511 using Type = Error;
512};
513
514template <> class WrappedHandlerReturn<ErrorSuccess> {
515public:
516 using Type = Error;
517};
518
519// Traits class that strips the response function from the list of handler
520// arguments.
521template <typename FnT> class AsyncHandlerTraits;
522
523template <typename ResultT, typename... ArgTs>
524class AsyncHandlerTraits<Error(std::function<Error(Expected<ResultT>)>, ArgTs...)> {
525public:
526 using Type = Error(ArgTs...);
527 using ResultType = Expected<ResultT>;
528};
529
530template <typename... ArgTs>
531class AsyncHandlerTraits<Error(std::function<Error(Error)>, ArgTs...)> {
532public:
533 using Type = Error(ArgTs...);
534 using ResultType = Error;
535};
536
537template <typename... ArgTs>
538class AsyncHandlerTraits<ErrorSuccess(std::function<Error(Error)>, ArgTs...)> {
539public:
540 using Type = Error(ArgTs...);
541 using ResultType = Error;
542};
543
544template <typename... ArgTs>
545class AsyncHandlerTraits<void(std::function<Error(Error)>, ArgTs...)> {
546public:
547 using Type = Error(ArgTs...);
548 using ResultType = Error;
549};
550
551template <typename ResponseHandlerT, typename... ArgTs>
552class AsyncHandlerTraits<Error(ResponseHandlerT, ArgTs...)> :
553 public AsyncHandlerTraits<Error(typename std::decay<ResponseHandlerT>::type,
554 ArgTs...)> {};
555
556// This template class provides utilities related to RPC function handlers.
557// The base case applies to non-function types (the template class is
558// specialized for function types) and inherits from the appropriate
559// speciilization for the given non-function type's call operator.
560template <typename HandlerT>
561class HandlerTraits : public HandlerTraits<decltype(
562 &std::remove_reference<HandlerT>::type::operator())> {
563};
564
565// Traits for handlers with a given function type.
566template <typename RetT, typename... ArgTs>
567class HandlerTraits<RetT(ArgTs...)> {
568public:
569 // Function type of the handler.
570 using Type = RetT(ArgTs...);
571
572 // Return type of the handler.
573 using ReturnType = RetT;
574
575 // Call the given handler with the given arguments.
576 template <typename HandlerT, typename... TArgTs>
577 static typename WrappedHandlerReturn<RetT>::Type
578 unpackAndRun(HandlerT &Handler, std::tuple<TArgTs...> &Args) {
579 return unpackAndRunHelper(Handler, Args,
580 llvm::index_sequence_for<TArgTs...>());
581 }
582
583 // Call the given handler with the given arguments.
584 template <typename HandlerT, typename ResponderT, typename... TArgTs>
585 static Error unpackAndRunAsync(HandlerT &Handler, ResponderT &Responder,
586 std::tuple<TArgTs...> &Args) {
587 return unpackAndRunAsyncHelper(Handler, Responder, Args,
588 llvm::index_sequence_for<TArgTs...>());
589 }
590
591 // Call the given handler with the given arguments.
592 template <typename HandlerT>
593 static typename std::enable_if<
594 std::is_void<typename HandlerTraits<HandlerT>::ReturnType>::value,
595 Error>::type
596 run(HandlerT &Handler, ArgTs &&... Args) {
597 Handler(std::move(Args)...);
598 return Error::success();
599 }
600
601 template <typename HandlerT, typename... TArgTs>
602 static typename std::enable_if<
603 !std::is_void<typename HandlerTraits<HandlerT>::ReturnType>::value,
604 typename HandlerTraits<HandlerT>::ReturnType>::type
605 run(HandlerT &Handler, TArgTs... Args) {
606 return Handler(std::move(Args)...);
607 }
608
609 // Serialize arguments to the channel.
610 template <typename ChannelT, typename... CArgTs>
611 static Error serializeArgs(ChannelT &C, const CArgTs... CArgs) {
612 return SequenceSerialization<ChannelT, ArgTs...>::serialize(C, CArgs...);
613 }
614
615 // Deserialize arguments from the channel.
616 template <typename ChannelT, typename... CArgTs>
617 static Error deserializeArgs(ChannelT &C, std::tuple<CArgTs...> &Args) {
618 return deserializeArgsHelper(C, Args,
619 llvm::index_sequence_for<CArgTs...>());
620 }
621
622private:
623 template <typename ChannelT, typename... CArgTs, size_t... Indexes>
624 static Error deserializeArgsHelper(ChannelT &C, std::tuple<CArgTs...> &Args,
625 llvm::index_sequence<Indexes...> _) {
626 return SequenceSerialization<ChannelT, ArgTs...>::deserialize(
627 C, std::get<Indexes>(Args)...);
628 }
629
630 template <typename HandlerT, typename ArgTuple, size_t... Indexes>
631 static typename WrappedHandlerReturn<
632 typename HandlerTraits<HandlerT>::ReturnType>::Type
633 unpackAndRunHelper(HandlerT &Handler, ArgTuple &Args,
634 llvm::index_sequence<Indexes...>) {
635 return run(Handler, std::move(std::get<Indexes>(Args))...);
636 }
637
638
639 template <typename HandlerT, typename ResponderT, typename ArgTuple,
640 size_t... Indexes>
641 static typename WrappedHandlerReturn<
642 typename HandlerTraits<HandlerT>::ReturnType>::Type
643 unpackAndRunAsyncHelper(HandlerT &Handler, ResponderT &Responder,
644 ArgTuple &Args,
645 llvm::index_sequence<Indexes...>) {
646 return run(Handler, Responder, std::move(std::get<Indexes>(Args))...);
647 }
648};
649
650// Handler traits for free functions.
651template <typename RetT, typename... ArgTs>
652class HandlerTraits<RetT(*)(ArgTs...)>
653 : public HandlerTraits<RetT(ArgTs...)> {};
654
655// Handler traits for class methods (especially call operators for lambdas).
656template <typename Class, typename RetT, typename... ArgTs>
657class HandlerTraits<RetT (Class::*)(ArgTs...)>
658 : public HandlerTraits<RetT(ArgTs...)> {};
659
660// Handler traits for const class methods (especially call operators for
661// lambdas).
662template <typename Class, typename RetT, typename... ArgTs>
663class HandlerTraits<RetT (Class::*)(ArgTs...) const>
664 : public HandlerTraits<RetT(ArgTs...)> {};
665
666// Utility to peel the Expected wrapper off a response handler error type.
667template <typename HandlerT> class ResponseHandlerArg;
668
669template <typename ArgT> class ResponseHandlerArg<Error(Expected<ArgT>)> {
670public:
671 using ArgType = Expected<ArgT>;
672 using UnwrappedArgType = ArgT;
673};
674
675template <typename ArgT>
676class ResponseHandlerArg<ErrorSuccess(Expected<ArgT>)> {
677public:
678 using ArgType = Expected<ArgT>;
679 using UnwrappedArgType = ArgT;
680};
681
682template <> class ResponseHandlerArg<Error(Error)> {
683public:
684 using ArgType = Error;
685};
686
687template <> class ResponseHandlerArg<ErrorSuccess(Error)> {
688public:
689 using ArgType = Error;
690};
691
692// ResponseHandler represents a handler for a not-yet-received function call
693// result.
694template <typename ChannelT> class ResponseHandler {
695public:
696 virtual ~ResponseHandler() {}
697
698 // Reads the function result off the wire and acts on it. The meaning of
699 // "act" will depend on how this method is implemented in any given
700 // ResponseHandler subclass but could, for example, mean running a
701 // user-specified handler or setting a promise value.
702 virtual Error handleResponse(ChannelT &C) = 0;
703
704 // Abandons this outstanding result.
705 virtual void abandon() = 0;
706
707 // Create an error instance representing an abandoned response.
708 static Error createAbandonedResponseError() {
709 return make_error<ResponseAbandoned>();
710 }
711};
712
713// ResponseHandler subclass for RPC functions with non-void returns.
714template <typename ChannelT, typename FuncRetT, typename HandlerT>
715class ResponseHandlerImpl : public ResponseHandler<ChannelT> {
716public:
717 ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {}
718
719 // Handle the result by deserializing it from the channel then passing it
720 // to the user defined handler.
721 Error handleResponse(ChannelT &C) override {
722 using UnwrappedArgType = typename ResponseHandlerArg<
723 typename HandlerTraits<HandlerT>::Type>::UnwrappedArgType;
724 UnwrappedArgType Result;
725 if (auto Err =
726 SerializationTraits<ChannelT, FuncRetT,
727 UnwrappedArgType>::deserialize(C, Result))
728 return Err;
729 if (auto Err = C.endReceiveMessage())
730 return Err;
731 return Handler(std::move(Result));
732 }
733
734 // Abandon this response by calling the handler with an 'abandoned response'
735 // error.
736 void abandon() override {
737 if (auto Err = Handler(this->createAbandonedResponseError())) {
738 // Handlers should not fail when passed an abandoned response error.
739 report_fatal_error(std::move(Err));
740 }
741 }
742
743private:
744 HandlerT Handler;
745};
746
747// ResponseHandler subclass for RPC functions with void returns.
748template <typename ChannelT, typename HandlerT>
749class ResponseHandlerImpl<ChannelT, void, HandlerT>
750 : public ResponseHandler<ChannelT> {
751public:
752 ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {}
753
754 // Handle the result (no actual value, just a notification that the function
755 // has completed on the remote end) by calling the user-defined handler with
756 // Error::success().
757 Error handleResponse(ChannelT &C) override {
758 if (auto Err = C.endReceiveMessage())
759 return Err;
760 return Handler(Error::success());
761 }
762
763 // Abandon this response by calling the handler with an 'abandoned response'
764 // error.
765 void abandon() override {
766 if (auto Err = Handler(this->createAbandonedResponseError())) {
767 // Handlers should not fail when passed an abandoned response error.
768 report_fatal_error(std::move(Err));
769 }
770 }
771
772private:
773 HandlerT Handler;
774};
775
776template <typename ChannelT, typename FuncRetT, typename HandlerT>
777class ResponseHandlerImpl<ChannelT, Expected<FuncRetT>, HandlerT>
778 : public ResponseHandler<ChannelT> {
779public:
780 ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {}
781
782 // Handle the result by deserializing it from the channel then passing it
783 // to the user defined handler.
784 Error handleResponse(ChannelT &C) override {
785 using HandlerArgType = typename ResponseHandlerArg<
786 typename HandlerTraits<HandlerT>::Type>::ArgType;
787 HandlerArgType Result((typename HandlerArgType::value_type()));
788
789 if (auto Err =
790 SerializationTraits<ChannelT, Expected<FuncRetT>,
791 HandlerArgType>::deserialize(C, Result))
792 return Err;
793 if (auto Err = C.endReceiveMessage())
794 return Err;
795 return Handler(std::move(Result));
796 }
797
798 // Abandon this response by calling the handler with an 'abandoned response'
799 // error.
800 void abandon() override {
801 if (auto Err = Handler(this->createAbandonedResponseError())) {
802 // Handlers should not fail when passed an abandoned response error.
803 report_fatal_error(std::move(Err));
804 }
805 }
806
807private:
808 HandlerT Handler;
809};
810
811template <typename ChannelT, typename HandlerT>
812class ResponseHandlerImpl<ChannelT, Error, HandlerT>
813 : public ResponseHandler<ChannelT> {
814public:
815 ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {}
816
817 // Handle the result by deserializing it from the channel then passing it
818 // to the user defined handler.
819 Error handleResponse(ChannelT &C) override {
820 Error Result = Error::success();
821 if (auto Err =
822 SerializationTraits<ChannelT, Error, Error>::deserialize(C, Result))
823 return Err;
824 if (auto Err = C.endReceiveMessage())
825 return Err;
826 return Handler(std::move(Result));
827 }
828
829 // Abandon this response by calling the handler with an 'abandoned response'
830 // error.
831 void abandon() override {
832 if (auto Err = Handler(this->createAbandonedResponseError())) {
833 // Handlers should not fail when passed an abandoned response error.
834 report_fatal_error(std::move(Err));
835 }
836 }
837
838private:
839 HandlerT Handler;
840};
841
842// Create a ResponseHandler from a given user handler.
843template <typename ChannelT, typename FuncRetT, typename HandlerT>
844std::unique_ptr<ResponseHandler<ChannelT>> createResponseHandler(HandlerT H) {
845 return llvm::make_unique<ResponseHandlerImpl<ChannelT, FuncRetT, HandlerT>>(
846 std::move(H));
847}
848
849// Helper for wrapping member functions up as functors. This is useful for
850// installing methods as result handlers.
851template <typename ClassT, typename RetT, typename... ArgTs>
852class MemberFnWrapper {
853public:
854 using MethodT = RetT (ClassT::*)(ArgTs...);
855 MemberFnWrapper(ClassT &Instance, MethodT Method)
856 : Instance(Instance), Method(Method) {}
857 RetT operator()(ArgTs &&... Args) {
858 return (Instance.*Method)(std::move(Args)...);
859 }
860
861private:
862 ClassT &Instance;
863 MethodT Method;
864};
865
866// Helper that provides a Functor for deserializing arguments.
867template <typename... ArgTs> class ReadArgs {
868public:
869 Error operator()() { return Error::success(); }
870};
871
872template <typename ArgT, typename... ArgTs>
873class ReadArgs<ArgT, ArgTs...> : public ReadArgs<ArgTs...> {
874public:
875 ReadArgs(ArgT &Arg, ArgTs &... Args)
876 : ReadArgs<ArgTs...>(Args...), Arg(Arg) {}
877
878 Error operator()(ArgT &ArgVal, ArgTs &... ArgVals) {
879 this->Arg = std::move(ArgVal);
880 return ReadArgs<ArgTs...>::operator()(ArgVals...);
881 }
882
883private:
884 ArgT &Arg;
885};
886
887// Manage sequence numbers.
888template <typename SequenceNumberT> class SequenceNumberManager {
889public:
890 // Reset, making all sequence numbers available.
891 void reset() {
892 std::lock_guard<std::mutex> Lock(SeqNoLock);
893 NextSequenceNumber = 0;
894 FreeSequenceNumbers.clear();
895 }
896
897 // Get the next available sequence number. Will re-use numbers that have
898 // been released.
899 SequenceNumberT getSequenceNumber() {
900 std::lock_guard<std::mutex> Lock(SeqNoLock);
901 if (FreeSequenceNumbers.empty())
902 return NextSequenceNumber++;
903 auto SequenceNumber = FreeSequenceNumbers.back();
904 FreeSequenceNumbers.pop_back();
905 return SequenceNumber;
906 }
907
908 // Release a sequence number, making it available for re-use.
909 void releaseSequenceNumber(SequenceNumberT SequenceNumber) {
910 std::lock_guard<std::mutex> Lock(SeqNoLock);
911 FreeSequenceNumbers.push_back(SequenceNumber);
912 }
913
914private:
915 std::mutex SeqNoLock;
916 SequenceNumberT NextSequenceNumber = 0;
917 std::vector<SequenceNumberT> FreeSequenceNumbers;
918};
919
920// Checks that predicate P holds for each corresponding pair of type arguments
921// from T1 and T2 tuple.
922template <template <class, class> class P, typename T1Tuple, typename T2Tuple>
923class RPCArgTypeCheckHelper;
924
925template <template <class, class> class P>
926class RPCArgTypeCheckHelper<P, std::tuple<>, std::tuple<>> {
927public:
928 static const bool value = true;
929};
930
931template <template <class, class> class P, typename T, typename... Ts,
932 typename U, typename... Us>
933class RPCArgTypeCheckHelper<P, std::tuple<T, Ts...>, std::tuple<U, Us...>> {
934public:
935 static const bool value =
936 P<T, U>::value &&
937 RPCArgTypeCheckHelper<P, std::tuple<Ts...>, std::tuple<Us...>>::value;
938};
939
940template <template <class, class> class P, typename T1Sig, typename T2Sig>
941class RPCArgTypeCheck {
942public:
943 using T1Tuple = typename FunctionArgsTuple<T1Sig>::Type;
944 using T2Tuple = typename FunctionArgsTuple<T2Sig>::Type;
945
946 static_assert(std::tuple_size<T1Tuple>::value >=
947 std::tuple_size<T2Tuple>::value,
948 "Too many arguments to RPC call");
949 static_assert(std::tuple_size<T1Tuple>::value <=
950 std::tuple_size<T2Tuple>::value,
951 "Too few arguments to RPC call");
952
953 static const bool value = RPCArgTypeCheckHelper<P, T1Tuple, T2Tuple>::value;
954};
955
956template <typename ChannelT, typename WireT, typename ConcreteT>
957class CanSerialize {
958private:
959 using S = SerializationTraits<ChannelT, WireT, ConcreteT>;
960
961 template <typename T>
962 static std::true_type
963 check(typename std::enable_if<
964 std::is_same<decltype(T::serialize(std::declval<ChannelT &>(),
965 std::declval<const ConcreteT &>())),
966 Error>::value,
967 void *>::type);
968
969 template <typename> static std::false_type check(...);
970
971public:
972 static const bool value = decltype(check<S>(0))::value;
973};
974
975template <typename ChannelT, typename WireT, typename ConcreteT>
976class CanDeserialize {
977private:
978 using S = SerializationTraits<ChannelT, WireT, ConcreteT>;
979
980 template <typename T>
981 static std::true_type
982 check(typename std::enable_if<
983 std::is_same<decltype(T::deserialize(std::declval<ChannelT &>(),
984 std::declval<ConcreteT &>())),
985 Error>::value,
986 void *>::type);
987
988 template <typename> static std::false_type check(...);
989
990public:
991 static const bool value = decltype(check<S>(0))::value;
992};
993
994/// Contains primitive utilities for defining, calling and handling calls to
995/// remote procedures. ChannelT is a bidirectional stream conforming to the
996/// RPCChannel interface (see RPCChannel.h), FunctionIdT is a procedure
997/// identifier type that must be serializable on ChannelT, and SequenceNumberT
998/// is an integral type that will be used to number in-flight function calls.
999///
1000/// These utilities support the construction of very primitive RPC utilities.
1001/// Their intent is to ensure correct serialization and deserialization of
1002/// procedure arguments, and to keep the client and server's view of the API in
1003/// sync.
1004template <typename ImplT, typename ChannelT, typename FunctionIdT,
1005 typename SequenceNumberT>
1006class RPCEndpointBase {
1007protected:
1008 class OrcRPCInvalid : public Function<OrcRPCInvalid, void()> {
1009 public:
1010 static const char *getName() { return "__orc_rpc$invalid"; }
1011 };
1012
1013 class OrcRPCResponse : public Function<OrcRPCResponse, void()> {
1014 public:
1015 static const char *getName() { return "__orc_rpc$response"; }
1016 };
1017
1018 class OrcRPCNegotiate
1019 : public Function<OrcRPCNegotiate, FunctionIdT(std::string)> {
1020 public:
1021 static const char *getName() { return "__orc_rpc$negotiate"; }
1022 };
1023
1024 // Helper predicate for testing for the presence of SerializeTraits
1025 // serializers.
1026 template <typename WireT, typename ConcreteT>
1027 class CanSerializeCheck : detail::CanSerialize<ChannelT, WireT, ConcreteT> {
1028 public:
1029 using detail::CanSerialize<ChannelT, WireT, ConcreteT>::value;
1030
1031 static_assert(value, "Missing serializer for argument (Can't serialize the "
1032 "first template type argument of CanSerializeCheck "
1033 "from the second)");
1034 };
1035
1036 // Helper predicate for testing for the presence of SerializeTraits
1037 // deserializers.
1038 template <typename WireT, typename ConcreteT>
1039 class CanDeserializeCheck
1040 : detail::CanDeserialize<ChannelT, WireT, ConcreteT> {
1041 public:
1042 using detail::CanDeserialize<ChannelT, WireT, ConcreteT>::value;
1043
1044 static_assert(value, "Missing deserializer for argument (Can't deserialize "
1045 "the second template type argument of "
1046 "CanDeserializeCheck from the first)");
1047 };
1048
1049public:
1050 /// Construct an RPC instance on a channel.
1051 RPCEndpointBase(ChannelT &C, bool LazyAutoNegotiation)
1052 : C(C), LazyAutoNegotiation(LazyAutoNegotiation) {
1053 // Hold ResponseId in a special variable, since we expect Response to be
1054 // called relatively frequently, and want to avoid the map lookup.
1055 ResponseId = FnIdAllocator.getResponseId();
1056 RemoteFunctionIds[OrcRPCResponse::getPrototype()] = ResponseId;
1057
1058 // Register the negotiate function id and handler.
1059 auto NegotiateId = FnIdAllocator.getNegotiateId();
1060 RemoteFunctionIds[OrcRPCNegotiate::getPrototype()] = NegotiateId;
1061 Handlers[NegotiateId] = wrapHandler<OrcRPCNegotiate>(
1062 [this](const std::string &Name) { return handleNegotiate(Name); });
1063 }
1064
1065
1066 /// Negotiate a function id for Func with the other end of the channel.
1067 template <typename Func> Error negotiateFunction(bool Retry = false) {
1068 return getRemoteFunctionId<Func>(true, Retry).takeError();
1069 }
1070
1071 /// Append a call Func, does not call send on the channel.
1072 /// The first argument specifies a user-defined handler to be run when the
1073 /// function returns. The handler should take an Expected<Func::ReturnType>,
1074 /// or an Error (if Func::ReturnType is void). The handler will be called
1075 /// with an error if the return value is abandoned due to a channel error.
1076 template <typename Func, typename HandlerT, typename... ArgTs>
1077 Error appendCallAsync(HandlerT Handler, const ArgTs &... Args) {
1078
1079 static_assert(
1080 detail::RPCArgTypeCheck<CanSerializeCheck, typename Func::Type,
1081 void(ArgTs...)>::value,
1082 "");
1083
1084 // Look up the function ID.
1085 FunctionIdT FnId;
1086 if (auto FnIdOrErr = getRemoteFunctionId<Func>(LazyAutoNegotiation, false))
1087 FnId = *FnIdOrErr;
1088 else {
1089 // Negotiation failed. Notify the handler then return the negotiate-failed
1090 // error.
1091 cantFail(Handler(make_error<ResponseAbandoned>()));
1092 return FnIdOrErr.takeError();
1093 }
1094
1095 SequenceNumberT SeqNo; // initialized in locked scope below.
1096 {
1097 // Lock the pending responses map and sequence number manager.
1098 std::lock_guard<std::mutex> Lock(ResponsesMutex);
1099
1100 // Allocate a sequence number.
1101 SeqNo = SequenceNumberMgr.getSequenceNumber();
1102 assert(!PendingResponses.count(SeqNo) &&(static_cast <bool> (!PendingResponses.count(SeqNo) &&
"Sequence number already allocated") ? void (0) : __assert_fail
("!PendingResponses.count(SeqNo) && \"Sequence number already allocated\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h"
, 1103, __extension__ __PRETTY_FUNCTION__))
1103 "Sequence number already allocated")(static_cast <bool> (!PendingResponses.count(SeqNo) &&
"Sequence number already allocated") ? void (0) : __assert_fail
("!PendingResponses.count(SeqNo) && \"Sequence number already allocated\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h"
, 1103, __extension__ __PRETTY_FUNCTION__))
;
1104
1105 // Install the user handler.
1106 PendingResponses[SeqNo] =
1107 detail::createResponseHandler<ChannelT, typename Func::ReturnType>(
1108 std::move(Handler));
1109 }
1110
1111 // Open the function call message.
1112 if (auto Err = C.startSendMessage(FnId, SeqNo)) {
1113 abandonPendingResponses();
1114 return Err;
1115 }
1116
1117 // Serialize the call arguments.
1118 if (auto Err = detail::HandlerTraits<typename Func::Type>::serializeArgs(
1119 C, Args...)) {
1120 abandonPendingResponses();
1121 return Err;
1122 }
1123
1124 // Close the function call messagee.
1125 if (auto Err = C.endSendMessage()) {
1126 abandonPendingResponses();
1127 return Err;
1128 }
1129
1130 return Error::success();
1131 }
1132
1133 Error sendAppendedCalls() { return C.send(); };
1134
1135 template <typename Func, typename HandlerT, typename... ArgTs>
1136 Error callAsync(HandlerT Handler, const ArgTs &... Args) {
1137 if (auto Err = appendCallAsync<Func>(std::move(Handler), Args...))
1138 return Err;
1139 return C.send();
1140 }
1141
1142 /// Handle one incoming call.
1143 Error handleOne() {
1144 FunctionIdT FnId;
1145 SequenceNumberT SeqNo;
7
'SeqNo' declared without an initial value
1146 if (auto Err = C.startReceiveMessage(FnId, SeqNo)) {
8
Calling 'RawByteChannel::startReceiveMessage'
135
Returning from 'RawByteChannel::startReceiveMessage'
136
Taking false branch
1147 abandonPendingResponses();
1148 return Err;
1149 }
1150 if (FnId == ResponseId)
137
Taking true branch
1151 return handleResponse(SeqNo);
138
1st function call argument is an uninitialized value
1152 auto I = Handlers.find(FnId);
1153 if (I != Handlers.end())
1154 return I->second(C, SeqNo);
1155
1156 // else: No handler found. Report error to client?
1157 return make_error<BadFunctionCall<FunctionIdT, SequenceNumberT>>(FnId,
1158 SeqNo);
1159 }
1160
1161 /// Helper for handling setter procedures - this method returns a functor that
1162 /// sets the variables referred to by Args... to values deserialized from the
1163 /// channel.
1164 /// E.g.
1165 ///
1166 /// typedef Function<0, bool, int> Func1;
1167 ///
1168 /// ...
1169 /// bool B;
1170 /// int I;
1171 /// if (auto Err = expect<Func1>(Channel, readArgs(B, I)))
1172 /// /* Handle Args */ ;
1173 ///
1174 template <typename... ArgTs>
1175 static detail::ReadArgs<ArgTs...> readArgs(ArgTs &... Args) {
1176 return detail::ReadArgs<ArgTs...>(Args...);
1177 }
1178
1179 /// Abandon all outstanding result handlers.
1180 ///
1181 /// This will call all currently registered result handlers to receive an
1182 /// "abandoned" error as their argument. This is used internally by the RPC
1183 /// in error situations, but can also be called directly by clients who are
1184 /// disconnecting from the remote and don't or can't expect responses to their
1185 /// outstanding calls. (Especially for outstanding blocking calls, calling
1186 /// this function may be necessary to avoid dead threads).
1187 void abandonPendingResponses() {
1188 // Lock the pending responses map and sequence number manager.
1189 std::lock_guard<std::mutex> Lock(ResponsesMutex);
1190
1191 for (auto &KV : PendingResponses)
1192 KV.second->abandon();
1193 PendingResponses.clear();
1194 SequenceNumberMgr.reset();
1195 }
1196
1197 /// Remove the handler for the given function.
1198 /// A handler must currently be registered for this function.
1199 template <typename Func>
1200 void removeHandler() {
1201 auto IdItr = LocalFunctionIds.find(Func::getPrototype());
1202 assert(IdItr != LocalFunctionIds.end() &&(static_cast <bool> (IdItr != LocalFunctionIds.end() &&
"Function does not have a registered handler") ? void (0) : __assert_fail
("IdItr != LocalFunctionIds.end() && \"Function does not have a registered handler\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h"
, 1203, __extension__ __PRETTY_FUNCTION__))
1203 "Function does not have a registered handler")(static_cast <bool> (IdItr != LocalFunctionIds.end() &&
"Function does not have a registered handler") ? void (0) : __assert_fail
("IdItr != LocalFunctionIds.end() && \"Function does not have a registered handler\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h"
, 1203, __extension__ __PRETTY_FUNCTION__))
;
1204 auto HandlerItr = Handlers.find(IdItr->second);
1205 assert(HandlerItr != Handlers.end() &&(static_cast <bool> (HandlerItr != Handlers.end() &&
"Function does not have a registered handler") ? void (0) : __assert_fail
("HandlerItr != Handlers.end() && \"Function does not have a registered handler\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h"
, 1206, __extension__ __PRETTY_FUNCTION__))
1206 "Function does not have a registered handler")(static_cast <bool> (HandlerItr != Handlers.end() &&
"Function does not have a registered handler") ? void (0) : __assert_fail
("HandlerItr != Handlers.end() && \"Function does not have a registered handler\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h"
, 1206, __extension__ __PRETTY_FUNCTION__))
;
1207 Handlers.erase(HandlerItr);
1208 }
1209
1210 /// Clear all handlers.
1211 void clearHandlers() {
1212 Handlers.clear();
1213 }
1214
1215protected:
1216
1217 FunctionIdT getInvalidFunctionId() const {
1218 return FnIdAllocator.getInvalidId();
1219 }
1220
1221 /// Add the given handler to the handler map and make it available for
1222 /// autonegotiation and execution.
1223 template <typename Func, typename HandlerT>
1224 void addHandlerImpl(HandlerT Handler) {
1225
1226 static_assert(detail::RPCArgTypeCheck<
1227 CanDeserializeCheck, typename Func::Type,
1228 typename detail::HandlerTraits<HandlerT>::Type>::value,
1229 "");
1230
1231 FunctionIdT NewFnId = FnIdAllocator.template allocate<Func>();
1232 LocalFunctionIds[Func::getPrototype()] = NewFnId;
1233 Handlers[NewFnId] = wrapHandler<Func>(std::move(Handler));
1234 }
1235
1236 template <typename Func, typename HandlerT>
1237 void addAsyncHandlerImpl(HandlerT Handler) {
1238
1239 static_assert(detail::RPCArgTypeCheck<
1240 CanDeserializeCheck, typename Func::Type,
1241 typename detail::AsyncHandlerTraits<
1242 typename detail::HandlerTraits<HandlerT>::Type
1243 >::Type>::value,
1244 "");
1245
1246 FunctionIdT NewFnId = FnIdAllocator.template allocate<Func>();
1247 LocalFunctionIds[Func::getPrototype()] = NewFnId;
1248 Handlers[NewFnId] = wrapAsyncHandler<Func>(std::move(Handler));
1249 }
1250
1251 Error handleResponse(SequenceNumberT SeqNo) {
1252 using Handler = typename decltype(PendingResponses)::mapped_type;
1253 Handler PRHandler;
1254
1255 {
1256 // Lock the pending responses map and sequence number manager.
1257 std::unique_lock<std::mutex> Lock(ResponsesMutex);
1258 auto I = PendingResponses.find(SeqNo);
1259
1260 if (I != PendingResponses.end()) {
1261 PRHandler = std::move(I->second);
1262 PendingResponses.erase(I);
1263 SequenceNumberMgr.releaseSequenceNumber(SeqNo);
1264 } else {
1265 // Unlock the pending results map to prevent recursive lock.
1266 Lock.unlock();
1267 abandonPendingResponses();
1268 return make_error<
1269 InvalidSequenceNumberForResponse<SequenceNumberT>>(SeqNo);
1270 }
1271 }
1272
1273 assert(PRHandler &&(static_cast <bool> (PRHandler && "If we didn't find a response handler we should have bailed out"
) ? void (0) : __assert_fail ("PRHandler && \"If we didn't find a response handler we should have bailed out\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h"
, 1274, __extension__ __PRETTY_FUNCTION__))
1274 "If we didn't find a response handler we should have bailed out")(static_cast <bool> (PRHandler && "If we didn't find a response handler we should have bailed out"
) ? void (0) : __assert_fail ("PRHandler && \"If we didn't find a response handler we should have bailed out\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h"
, 1274, __extension__ __PRETTY_FUNCTION__))
;
1275
1276 if (auto Err = PRHandler->handleResponse(C)) {
1277 abandonPendingResponses();
1278 return Err;
1279 }
1280
1281 return Error::success();
1282 }
1283
1284 FunctionIdT handleNegotiate(const std::string &Name) {
1285 auto I = LocalFunctionIds.find(Name);
1286 if (I == LocalFunctionIds.end())
1287 return getInvalidFunctionId();
1288 return I->second;
1289 }
1290
1291 // Find the remote FunctionId for the given function.
1292 template <typename Func>
1293 Expected<FunctionIdT> getRemoteFunctionId(bool NegotiateIfNotInMap,
1294 bool NegotiateIfInvalid) {
1295 bool DoNegotiate;
1296
1297 // Check if we already have a function id...
1298 auto I = RemoteFunctionIds.find(Func::getPrototype());
1299 if (I != RemoteFunctionIds.end()) {
1300 // If it's valid there's nothing left to do.
1301 if (I->second != getInvalidFunctionId())
1302 return I->second;
1303 DoNegotiate = NegotiateIfInvalid;
1304 } else
1305 DoNegotiate = NegotiateIfNotInMap;
1306
1307 // We don't have a function id for Func yet, but we're allowed to try to
1308 // negotiate one.
1309 if (DoNegotiate) {
1310 auto &Impl = static_cast<ImplT &>(*this);
1311 if (auto RemoteIdOrErr =
1312 Impl.template callB<OrcRPCNegotiate>(Func::getPrototype())) {
1313 RemoteFunctionIds[Func::getPrototype()] = *RemoteIdOrErr;
1314 if (*RemoteIdOrErr == getInvalidFunctionId())
1315 return make_error<CouldNotNegotiate>(Func::getPrototype());
1316 return *RemoteIdOrErr;
1317 } else
1318 return RemoteIdOrErr.takeError();
1319 }
1320
1321 // No key was available in the map and we weren't allowed to try to
1322 // negotiate one, so return an unknown function error.
1323 return make_error<CouldNotNegotiate>(Func::getPrototype());
1324 }
1325
1326 using WrappedHandlerFn = std::function<Error(ChannelT &, SequenceNumberT)>;
1327
1328 // Wrap the given user handler in the necessary argument-deserialization code,
1329 // result-serialization code, and call to the launch policy (if present).
1330 template <typename Func, typename HandlerT>
1331 WrappedHandlerFn wrapHandler(HandlerT Handler) {
1332 return [this, Handler](ChannelT &Channel,
1333 SequenceNumberT SeqNo) mutable -> Error {
1334 // Start by deserializing the arguments.
1335 using ArgsTuple =
1336 typename detail::FunctionArgsTuple<
1337 typename detail::HandlerTraits<HandlerT>::Type>::Type;
1338 auto Args = std::make_shared<ArgsTuple>();
1339
1340 if (auto Err =
1341 detail::HandlerTraits<typename Func::Type>::deserializeArgs(
1342 Channel, *Args))
1343 return Err;
1344
1345 // GCC 4.7 and 4.8 incorrectly issue a -Wunused-but-set-variable warning
1346 // for RPCArgs. Void cast RPCArgs to work around this for now.
1347 // FIXME: Remove this workaround once we can assume a working GCC version.
1348 (void)Args;
1349
1350 // End receieve message, unlocking the channel for reading.
1351 if (auto Err = Channel.endReceiveMessage())
1352 return Err;
1353
1354 using HTraits = detail::HandlerTraits<HandlerT>;
1355 using FuncReturn = typename Func::ReturnType;
1356 return detail::respond<FuncReturn>(Channel, ResponseId, SeqNo,
1357 HTraits::unpackAndRun(Handler, *Args));
1358 };
1359 }
1360
1361 // Wrap the given user handler in the necessary argument-deserialization code,
1362 // result-serialization code, and call to the launch policy (if present).
1363 template <typename Func, typename HandlerT>
1364 WrappedHandlerFn wrapAsyncHandler(HandlerT Handler) {
1365 return [this, Handler](ChannelT &Channel,
1366 SequenceNumberT SeqNo) mutable -> Error {
1367 // Start by deserializing the arguments.
1368 using AHTraits = detail::AsyncHandlerTraits<
1369 typename detail::HandlerTraits<HandlerT>::Type>;
1370 using ArgsTuple =
1371 typename detail::FunctionArgsTuple<typename AHTraits::Type>::Type;
1372 auto Args = std::make_shared<ArgsTuple>();
1373
1374 if (auto Err =
1375 detail::HandlerTraits<typename Func::Type>::deserializeArgs(
1376 Channel, *Args))
1377 return Err;
1378
1379 // GCC 4.7 and 4.8 incorrectly issue a -Wunused-but-set-variable warning
1380 // for RPCArgs. Void cast RPCArgs to work around this for now.
1381 // FIXME: Remove this workaround once we can assume a working GCC version.
1382 (void)Args;
1383
1384 // End receieve message, unlocking the channel for reading.
1385 if (auto Err = Channel.endReceiveMessage())
1386 return Err;
1387
1388 using HTraits = detail::HandlerTraits<HandlerT>;
1389 using FuncReturn = typename Func::ReturnType;
1390 auto Responder =
1391 [this, SeqNo](typename AHTraits::ResultType RetVal) -> Error {
1392 return detail::respond<FuncReturn>(C, ResponseId, SeqNo,
1393 std::move(RetVal));
1394 };
1395
1396 return HTraits::unpackAndRunAsync(Handler, Responder, *Args);
1397 };
1398 }
1399
1400 ChannelT &C;
1401
1402 bool LazyAutoNegotiation;
1403
1404 RPCFunctionIdAllocator<FunctionIdT> FnIdAllocator;
1405
1406 FunctionIdT ResponseId;
1407 std::map<std::string, FunctionIdT> LocalFunctionIds;
1408 std::map<const char *, FunctionIdT> RemoteFunctionIds;
1409
1410 std::map<FunctionIdT, WrappedHandlerFn> Handlers;
1411
1412 std::mutex ResponsesMutex;
1413 detail::SequenceNumberManager<SequenceNumberT> SequenceNumberMgr;
1414 std::map<SequenceNumberT, std::unique_ptr<detail::ResponseHandler<ChannelT>>>
1415 PendingResponses;
1416};
1417
1418} // end namespace detail
1419
1420template <typename ChannelT, typename FunctionIdT = uint32_t,
1421 typename SequenceNumberT = uint32_t>
1422class MultiThreadedRPCEndpoint
1423 : public detail::RPCEndpointBase<
1424 MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
1425 ChannelT, FunctionIdT, SequenceNumberT> {
1426private:
1427 using BaseClass =
1428 detail::RPCEndpointBase<
1429 MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
1430 ChannelT, FunctionIdT, SequenceNumberT>;
1431
1432public:
1433 MultiThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation)
1434 : BaseClass(C, LazyAutoNegotiation) {}
1435
1436 /// Add a handler for the given RPC function.
1437 /// This installs the given handler functor for the given RPC Function, and
1438 /// makes the RPC function available for negotiation/calling from the remote.
1439 template <typename Func, typename HandlerT>
1440 void addHandler(HandlerT Handler) {
1441 return this->template addHandlerImpl<Func>(std::move(Handler));
1442 }
1443
1444 /// Add a class-method as a handler.
1445 template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
1446 void addHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) {
1447 addHandler<Func>(
1448 detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
1449 }
1450
1451 template <typename Func, typename HandlerT>
1452 void addAsyncHandler(HandlerT Handler) {
1453 return this->template addAsyncHandlerImpl<Func>(std::move(Handler));
1454 }
1455
1456 /// Add a class-method as a handler.
1457 template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
1458 void addAsyncHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) {
1459 addAsyncHandler<Func>(
1460 detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
1461 }
1462
1463 /// Return type for non-blocking call primitives.
1464 template <typename Func>
1465 using NonBlockingCallResult = typename detail::ResultTraits<
1466 typename Func::ReturnType>::ReturnFutureType;
1467
1468 /// Call Func on Channel C. Does not block, does not call send. Returns a pair
1469 /// of a future result and the sequence number assigned to the result.
1470 ///
1471 /// This utility function is primarily used for single-threaded mode support,
1472 /// where the sequence number can be used to wait for the corresponding
1473 /// result. In multi-threaded mode the appendCallNB method, which does not
1474 /// return the sequence numeber, should be preferred.
1475 template <typename Func, typename... ArgTs>
1476 Expected<NonBlockingCallResult<Func>> appendCallNB(const ArgTs &... Args) {
1477 using RTraits = detail::ResultTraits<typename Func::ReturnType>;
1478 using ErrorReturn = typename RTraits::ErrorReturnType;
1479 using ErrorReturnPromise = typename RTraits::ReturnPromiseType;
1480
1481 // FIXME: Stack allocate and move this into the handler once LLVM builds
1482 // with C++14.
1483 auto Promise = std::make_shared<ErrorReturnPromise>();
1484 auto FutureResult = Promise->get_future();
1485
1486 if (auto Err = this->template appendCallAsync<Func>(
1487 [Promise](ErrorReturn RetOrErr) {
1488 Promise->set_value(std::move(RetOrErr));
1489 return Error::success();
1490 },
1491 Args...)) {
1492 RTraits::consumeAbandoned(FutureResult.get());
1493 return std::move(Err);
1494 }
1495 return std::move(FutureResult);
1496 }
1497
1498 /// The same as appendCallNBWithSeq, except that it calls C.send() to
1499 /// flush the channel after serializing the call.
1500 template <typename Func, typename... ArgTs>
1501 Expected<NonBlockingCallResult<Func>> callNB(const ArgTs &... Args) {
1502 auto Result = appendCallNB<Func>(Args...);
1503 if (!Result)
1504 return Result;
1505 if (auto Err = this->C.send()) {
1506 this->abandonPendingResponses();
1507 detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned(
1508 std::move(Result->get()));
1509 return std::move(Err);
1510 }
1511 return Result;
1512 }
1513
1514 /// Call Func on Channel C. Blocks waiting for a result. Returns an Error
1515 /// for void functions or an Expected<T> for functions returning a T.
1516 ///
1517 /// This function is for use in threaded code where another thread is
1518 /// handling responses and incoming calls.
1519 template <typename Func, typename... ArgTs,
1520 typename AltRetT = typename Func::ReturnType>
1521 typename detail::ResultTraits<AltRetT>::ErrorReturnType
1522 callB(const ArgTs &... Args) {
1523 if (auto FutureResOrErr = callNB<Func>(Args...))
1524 return FutureResOrErr->get();
1525 else
1526 return FutureResOrErr.takeError();
1527 }
1528
1529 /// Handle incoming RPC calls.
1530 Error handlerLoop() {
1531 while (true)
1532 if (auto Err = this->handleOne())
1533 return Err;
1534 return Error::success();
1535 }
1536};
1537
1538template <typename ChannelT, typename FunctionIdT = uint32_t,
1539 typename SequenceNumberT = uint32_t>
1540class SingleThreadedRPCEndpoint
1541 : public detail::RPCEndpointBase<
1542 SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
1543 ChannelT, FunctionIdT, SequenceNumberT> {
1544private:
1545 using BaseClass =
1546 detail::RPCEndpointBase<
1547 SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>,
1548 ChannelT, FunctionIdT, SequenceNumberT>;
1549
1550public:
1551 SingleThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation)
1552 : BaseClass(C, LazyAutoNegotiation) {}
1553
1554 template <typename Func, typename HandlerT>
1555 void addHandler(HandlerT Handler) {
1556 return this->template addHandlerImpl<Func>(std::move(Handler));
1557 }
1558
1559 template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
1560 void addHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) {
1561 addHandler<Func>(
1562 detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
1563 }
1564
1565 template <typename Func, typename HandlerT>
1566 void addAsyncHandler(HandlerT Handler) {
1567 return this->template addAsyncHandlerImpl<Func>(std::move(Handler));
1568 }
1569
1570 /// Add a class-method as a handler.
1571 template <typename Func, typename ClassT, typename RetT, typename... ArgTs>
1572 void addAsyncHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) {
1573 addAsyncHandler<Func>(
1574 detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method));
1575 }
1576
1577 template <typename Func, typename... ArgTs,
1578 typename AltRetT = typename Func::ReturnType>
1579 typename detail::ResultTraits<AltRetT>::ErrorReturnType
1580 callB(const ArgTs &... Args) {
1581 bool ReceivedResponse = false;
1582 using ResultType = typename detail::ResultTraits<AltRetT>::ErrorReturnType;
1583 auto Result = detail::ResultTraits<AltRetT>::createBlankErrorReturnValue();
1584
1585 // We have to 'Check' result (which we know is in a success state at this
1586 // point) so that it can be overwritten in the async handler.
1587 (void)!!Result;
1588
1589 if (auto Err = this->template appendCallAsync<Func>(
1590 [&](ResultType R) {
1591 Result = std::move(R);
1592 ReceivedResponse = true;
1593 return Error::success();
1594 },
1595 Args...)) {
1596 detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned(
1597 std::move(Result));
1598 return std::move(Err);
1599 }
1600
1601 while (!ReceivedResponse) {
1602 if (auto Err = this->handleOne()) {
1603 detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned(
1604 std::move(Result));
1605 return std::move(Err);
1606 }
1607 }
1608
1609 return Result;
1610 }
1611};
1612
1613/// Asynchronous dispatch for a function on an RPC endpoint.
1614template <typename RPCClass, typename Func>
1615class RPCAsyncDispatch {
1616public:
1617 RPCAsyncDispatch(RPCClass &Endpoint) : Endpoint(Endpoint) {}
1618
1619 template <typename HandlerT, typename... ArgTs>
1620 Error operator()(HandlerT Handler, const ArgTs &... Args) const {
1621 return Endpoint.template appendCallAsync<Func>(std::move(Handler), Args...);
1622 }
1623
1624private:
1625 RPCClass &Endpoint;
1626};
1627
1628/// Construct an asynchronous dispatcher from an RPC endpoint and a Func.
1629template <typename Func, typename RPCEndpointT>
1630RPCAsyncDispatch<RPCEndpointT, Func> rpcAsyncDispatch(RPCEndpointT &Endpoint) {
1631 return RPCAsyncDispatch<RPCEndpointT, Func>(Endpoint);
1632}
1633
1634/// \brief Allows a set of asynchrounous calls to be dispatched, and then
1635/// waited on as a group.
1636class ParallelCallGroup {
1637public:
1638
1639 ParallelCallGroup() = default;
1640 ParallelCallGroup(const ParallelCallGroup &) = delete;
1641 ParallelCallGroup &operator=(const ParallelCallGroup &) = delete;
1642
1643 /// \brief Make as asynchronous call.
1644 template <typename AsyncDispatcher, typename HandlerT, typename... ArgTs>
1645 Error call(const AsyncDispatcher &AsyncDispatch, HandlerT Handler,
1646 const ArgTs &... Args) {
1647 // Increment the count of outstanding calls. This has to happen before
1648 // we invoke the call, as the handler may (depending on scheduling)
1649 // be run immediately on another thread, and we don't want the decrement
1650 // in the wrapped handler below to run before the increment.
1651 {
1652 std::unique_lock<std::mutex> Lock(M);
1653 ++NumOutstandingCalls;
1654 }
1655
1656 // Wrap the user handler in a lambda that will decrement the
1657 // outstanding calls count, then poke the condition variable.
1658 using ArgType = typename detail::ResponseHandlerArg<
1659 typename detail::HandlerTraits<HandlerT>::Type>::ArgType;
1660 // FIXME: Move handler into wrapped handler once we have C++14.
1661 auto WrappedHandler = [this, Handler](ArgType Arg) {
1662 auto Err = Handler(std::move(Arg));
1663 std::unique_lock<std::mutex> Lock(M);
1664 --NumOutstandingCalls;
1665 CV.notify_all();
1666 return Err;
1667 };
1668
1669 return AsyncDispatch(std::move(WrappedHandler), Args...);
1670 }
1671
1672 /// \brief Blocks until all calls have been completed and their return value
1673 /// handlers run.
1674 void wait() {
1675 std::unique_lock<std::mutex> Lock(M);
1676 while (NumOutstandingCalls > 0)
1677 CV.wait(Lock);
1678 }
1679
1680private:
1681 std::mutex M;
1682 std::condition_variable CV;
1683 uint32_t NumOutstandingCalls = 0;
1684};
1685
1686/// @brief Convenience class for grouping RPC Functions into APIs that can be
1687/// negotiated as a block.
1688///
1689template <typename... Funcs>
1690class APICalls {
1691public:
1692
1693 /// @brief Test whether this API contains Function F.
1694 template <typename F>
1695 class Contains {
1696 public:
1697 static const bool value = false;
1698 };
1699
1700 /// @brief Negotiate all functions in this API.
1701 template <typename RPCEndpoint>
1702 static Error negotiate(RPCEndpoint &R) {
1703 return Error::success();
1704 }
1705};
1706
1707template <typename Func, typename... Funcs>
1708class APICalls<Func, Funcs...> {
1709public:
1710
1711 template <typename F>
1712 class Contains {
1713 public:
1714 static const bool value = std::is_same<F, Func>::value |
1715 APICalls<Funcs...>::template Contains<F>::value;
1716 };
1717
1718 template <typename RPCEndpoint>
1719 static Error negotiate(RPCEndpoint &R) {
1720 if (auto Err = R.template negotiateFunction<Func>())
1721 return Err;
1722 return APICalls<Funcs...>::negotiate(R);
1723 }
1724
1725};
1726
1727template <typename... InnerFuncs, typename... Funcs>
1728class APICalls<APICalls<InnerFuncs...>, Funcs...> {
1729public:
1730
1731 template <typename F>
1732 class Contains {
1733 public:
1734 static const bool value =
1735 APICalls<InnerFuncs...>::template Contains<F>::value |
1736 APICalls<Funcs...>::template Contains<F>::value;
1737 };
1738
1739 template <typename RPCEndpoint>
1740 static Error negotiate(RPCEndpoint &R) {
1741 if (auto Err = APICalls<InnerFuncs...>::negotiate(R))
1742 return Err;
1743 return APICalls<Funcs...>::negotiate(R);
1744 }
1745
1746};
1747
1748} // end namespace rpc
1749} // end namespace orc
1750} // end namespace llvm
1751
1752#endif

/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RawByteChannel.h

1//===- llvm/ExecutionEngine/Orc/RawByteChannel.h ----------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H
11#define LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H
12
13#include "llvm/ADT/StringRef.h"
14#include "llvm/ExecutionEngine/Orc/RPCSerialization.h"
15#include "llvm/Support/Endian.h"
16#include "llvm/Support/Error.h"
17#include <cstdint>
18#include <mutex>
19#include <string>
20#include <type_traits>
21
22namespace llvm {
23namespace orc {
24namespace rpc {
25
26/// Interface for byte-streams to be used with RPC.
27class RawByteChannel {
28public:
29 virtual ~RawByteChannel() = default;
30
31 /// Read Size bytes from the stream into *Dst.
32 virtual Error readBytes(char *Dst, unsigned Size) = 0;
33
34 /// Read size bytes from *Src and append them to the stream.
35 virtual Error appendBytes(const char *Src, unsigned Size) = 0;
36
37 /// Flush the stream if possible.
38 virtual Error send() = 0;
39
40 /// Notify the channel that we're starting a message send.
41 /// Locks the channel for writing.
42 template <typename FunctionIdT, typename SequenceIdT>
43 Error startSendMessage(const FunctionIdT &FnId, const SequenceIdT &SeqNo) {
44 writeLock.lock();
45 if (auto Err = serializeSeq(*this, FnId, SeqNo)) {
46 writeLock.unlock();
47 return Err;
48 }
49 return Error::success();
50 }
51
52 /// Notify the channel that we're ending a message send.
53 /// Unlocks the channel for writing.
54 Error endSendMessage() {
55 writeLock.unlock();
56 return Error::success();
57 }
58
59 /// Notify the channel that we're starting a message receive.
60 /// Locks the channel for reading.
61 template <typename FunctionIdT, typename SequenceNumberT>
62 Error startReceiveMessage(FunctionIdT &FnId, SequenceNumberT &SeqNo) {
63 readLock.lock();
9
Calling 'mutex::lock'
15
Returning from 'mutex::lock'
64 if (auto Err = deserializeSeq(*this, FnId, SeqNo)) {
16
Calling 'deserializeSeq'
88
Returning from 'deserializeSeq'
89
Calling move constructor for 'Error'
113
Returning from move constructor for 'Error'
114
Calling 'Error::operator bool'
123
Returning from 'Error::operator bool'
124
Taking false branch
65 readLock.unlock();
66 return Err;
67 }
125
Calling '~Error'
132
Returning from '~Error'
68 return Error::success();
133
Calling 'Error::success'
134
Returning from 'Error::success'
69 }
70
71 /// Notify the channel that we're ending a message receive.
72 /// Unlocks the channel for reading.
73 Error endReceiveMessage() {
74 readLock.unlock();
75 return Error::success();
76 }
77
78 /// Get the lock for stream reading.
79 std::mutex &getReadLock() { return readLock; }
80
81 /// Get the lock for stream writing.
82 std::mutex &getWriteLock() { return writeLock; }
83
84private:
85 std::mutex readLock, writeLock;
86};
87
88template <typename ChannelT, typename T>
89class SerializationTraits<
90 ChannelT, T, T,
91 typename std::enable_if<
92 std::is_base_of<RawByteChannel, ChannelT>::value &&
93 (std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value ||
94 std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value ||
95 std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value ||
96 std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value ||
97 std::is_same<T, char>::value)>::type> {
98public:
99 static Error serialize(ChannelT &C, T V) {
100 support::endian::byte_swap<T, support::big>(V);
101 return C.appendBytes(reinterpret_cast<const char *>(&V), sizeof(T));
102 };
103
104 static Error deserialize(ChannelT &C, T &V) {
105 if (auto Err = C.readBytes(reinterpret_cast<char *>(&V), sizeof(T)))
19
Calling move constructor for 'Error'
30
Returning from move constructor for 'Error'
31
Calling 'Error::operator bool'
36
Returning from 'Error::operator bool'
37
Taking true branch
106 return Err;
38
Calling '~Error'
41
Returning from '~Error'
107 support::endian::byte_swap<T, support::big>(V);
108 return Error::success();
109 };
110};
111
112template <typename ChannelT>
113class SerializationTraits<ChannelT, bool, bool,
114 typename std::enable_if<std::is_base_of<
115 RawByteChannel, ChannelT>::value>::type> {
116public:
117 static Error serialize(ChannelT &C, bool V) {
118 uint8_t Tmp = V ? 1 : 0;
119 if (auto Err =
120 C.appendBytes(reinterpret_cast<const char *>(&Tmp), 1))
121 return Err;
122 return Error::success();
123 }
124
125 static Error deserialize(ChannelT &C, bool &V) {
126 uint8_t Tmp = 0;
127 if (auto Err = C.readBytes(reinterpret_cast<char *>(&Tmp), 1))
128 return Err;
129 V = Tmp != 0;
130 return Error::success();
131 }
132};
133
134template <typename ChannelT>
135class SerializationTraits<ChannelT, std::string, StringRef,
136 typename std::enable_if<std::is_base_of<
137 RawByteChannel, ChannelT>::value>::type> {
138public:
139 /// RPC channel serialization for std::strings.
140 static Error serialize(RawByteChannel &C, StringRef S) {
141 if (auto Err = serializeSeq(C, static_cast<uint64_t>(S.size())))
142 return Err;
143 return C.appendBytes((const char *)S.data(), S.size());
144 }
145};
146
147template <typename ChannelT, typename T>
148class SerializationTraits<ChannelT, std::string, T,
149 typename std::enable_if<
150 std::is_base_of<RawByteChannel, ChannelT>::value &&
151 (std::is_same<T, const char*>::value ||
152 std::is_same<T, char*>::value)>::type> {
153public:
154 static Error serialize(RawByteChannel &C, const char *S) {
155 return SerializationTraits<ChannelT, std::string, StringRef>::serialize(C,
156 S);
157 }
158};
159
160template <typename ChannelT>
161class SerializationTraits<ChannelT, std::string, std::string,
162 typename std::enable_if<std::is_base_of<
163 RawByteChannel, ChannelT>::value>::type> {
164public:
165 /// RPC channel serialization for std::strings.
166 static Error serialize(RawByteChannel &C, const std::string &S) {
167 return SerializationTraits<ChannelT, std::string, StringRef>::serialize(C,
168 S);
169 }
170
171 /// RPC channel deserialization for std::strings.
172 static Error deserialize(RawByteChannel &C, std::string &S) {
173 uint64_t Count = 0;
174 if (auto Err = deserializeSeq(C, Count))
175 return Err;
176 S.resize(Count);
177 return C.readBytes(&S[0], Count);
178 }
179};
180
181} // end namespace rpc
182} // end namespace orc
183} // end namespace llvm
184
185#endif // LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H

/usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/bits/std_mutex.h

1// std::mutex implementation -*- C++ -*-
2
3// Copyright (C) 2003-2017 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/std_mutex.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{mutex}
28 */
29
30#ifndef _GLIBCXX_MUTEX_H1
31#define _GLIBCXX_MUTEX_H1 1
32
33#pragma GCC system_header
34
35#if __cplusplus201103L < 201103L
36# include <bits/c++0x_warning.h>
37#else
38
39#include <system_error>
40#include <bits/functexcept.h>
41#include <bits/gthr.h>
42#include <bits/move.h> // for std::swap
43
44#ifdef _GLIBCXX_USE_C99_STDINT_TR11
45
46namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
47{
48_GLIBCXX_BEGIN_NAMESPACE_VERSION
49
50 /**
51 * @defgroup mutexes Mutexes
52 * @ingroup concurrency
53 *
54 * Classes for mutex support.
55 * @{
56 */
57
58#ifdef _GLIBCXX_HAS_GTHREADS1
59 // Common base class for std::mutex and std::timed_mutex
60 class __mutex_base
61 {
62 protected:
63 typedef __gthread_mutex_t __native_type;
64
65#ifdef __GTHREAD_MUTEX_INIT{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } }
66 __native_type _M_mutex = __GTHREAD_MUTEX_INIT{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } };
67
68 constexpr __mutex_base() noexcept = default;
69#else
70 __native_type _M_mutex;
71
72 __mutex_base() noexcept
73 {
74 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
75 __GTHREAD_MUTEX_INIT_FUNCTION__gthread_mutex_init_function(&_M_mutex);
76 }
77
78 ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); }
79#endif
80
81 __mutex_base(const __mutex_base&) = delete;
82 __mutex_base& operator=(const __mutex_base&) = delete;
83 };
84
85 /// The standard mutex type.
86 class mutex : private __mutex_base
87 {
88 public:
89 typedef __native_type* native_handle_type;
90
91#ifdef __GTHREAD_MUTEX_INIT{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } }
92 constexpr
93#endif
94 mutex() noexcept = default;
95 ~mutex() = default;
96
97 mutex(const mutex&) = delete;
98 mutex& operator=(const mutex&) = delete;
99
100 void
101 lock()
102 {
103 int __e = __gthread_mutex_lock(&_M_mutex);
10
Calling '__gthread_mutex_lock'
13
Returning from '__gthread_mutex_lock'
104
105 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
106 if (__e)
14
Taking false branch
107 __throw_system_error(__e);
108 }
109
110 bool
111 try_lock() noexcept
112 {
113 // XXX EINVAL, EAGAIN, EBUSY
114 return !__gthread_mutex_trylock(&_M_mutex);
115 }
116
117 void
118 unlock()
119 {
120 // XXX EINVAL, EAGAIN, EPERM
121 __gthread_mutex_unlock(&_M_mutex);
122 }
123
124 native_handle_type
125 native_handle() noexcept
126 { return &_M_mutex; }
127 };
128
129#endif // _GLIBCXX_HAS_GTHREADS
130
131 /// Do not acquire ownership of the mutex.
132 struct defer_lock_t { explicit defer_lock_t() = default; };
133
134 /// Try to acquire ownership of the mutex without blocking.
135 struct try_to_lock_t { explicit try_to_lock_t() = default; };
136
137 /// Assume the calling thread has already obtained mutex ownership
138 /// and manage it.
139 struct adopt_lock_t { explicit adopt_lock_t() = default; };
140
141 /// Tag used to prevent a scoped lock from acquiring ownership of a mutex.
142 _GLIBCXX17_INLINE constexpr defer_lock_t defer_lock { };
143
144 /// Tag used to prevent a scoped lock from blocking if a mutex is locked.
145 _GLIBCXX17_INLINE constexpr try_to_lock_t try_to_lock { };
146
147 /// Tag used to make a scoped lock take ownership of a locked mutex.
148 _GLIBCXX17_INLINE constexpr adopt_lock_t adopt_lock { };
149
150 /** @brief A simple scoped lock type.
151 *
152 * A lock_guard controls mutex ownership within a scope, releasing
153 * ownership in the destructor.
154 */
155 template<typename _Mutex>
156 class lock_guard
157 {
158 public:
159 typedef _Mutex mutex_type;
160
161 explicit lock_guard(mutex_type& __m) : _M_device(__m)
162 { _M_device.lock(); }
163
164 lock_guard(mutex_type& __m, adopt_lock_t) noexcept : _M_device(__m)
165 { } // calling thread owns mutex
166
167 ~lock_guard()
168 { _M_device.unlock(); }
169
170 lock_guard(const lock_guard&) = delete;
171 lock_guard& operator=(const lock_guard&) = delete;
172
173 private:
174 mutex_type& _M_device;
175 };
176
177 /** @brief A movable scoped lock type.
178 *
179 * A unique_lock controls mutex ownership within a scope. Ownership of the
180 * mutex can be delayed until after construction and can be transferred
181 * to another unique_lock by move construction or move assignment. If a
182 * mutex lock is owned when the destructor runs ownership will be released.
183 */
184 template<typename _Mutex>
185 class unique_lock
186 {
187 public:
188 typedef _Mutex mutex_type;
189
190 unique_lock() noexcept
191 : _M_device(0), _M_owns(false)
192 { }
193
194 explicit unique_lock(mutex_type& __m)
195 : _M_device(std::__addressof(__m)), _M_owns(false)
196 {
197 lock();
198 _M_owns = true;
199 }
200
201 unique_lock(mutex_type& __m, defer_lock_t) noexcept
202 : _M_device(std::__addressof(__m)), _M_owns(false)
203 { }
204
205 unique_lock(mutex_type& __m, try_to_lock_t)
206 : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock())
207 { }
208
209 unique_lock(mutex_type& __m, adopt_lock_t) noexcept
210 : _M_device(std::__addressof(__m)), _M_owns(true)
211 {
212 // XXX calling thread owns mutex
213 }
214
215 template<typename _Clock, typename _Duration>
216 unique_lock(mutex_type& __m,
217 const chrono::time_point<_Clock, _Duration>& __atime)
218 : _M_device(std::__addressof(__m)),
219 _M_owns(_M_device->try_lock_until(__atime))
220 { }
221
222 template<typename _Rep, typename _Period>
223 unique_lock(mutex_type& __m,
224 const chrono::duration<_Rep, _Period>& __rtime)
225 : _M_device(std::__addressof(__m)),
226 _M_owns(_M_device->try_lock_for(__rtime))
227 { }
228
229 ~unique_lock()
230 {
231 if (_M_owns)
232 unlock();
233 }
234
235 unique_lock(const unique_lock&) = delete;
236 unique_lock& operator=(const unique_lock&) = delete;
237
238 unique_lock(unique_lock&& __u) noexcept
239 : _M_device(__u._M_device), _M_owns(__u._M_owns)
240 {
241 __u._M_device = 0;
242 __u._M_owns = false;
243 }
244
245 unique_lock& operator=(unique_lock&& __u) noexcept
246 {
247 if(_M_owns)
248 unlock();
249
250 unique_lock(std::move(__u)).swap(*this);
251
252 __u._M_device = 0;
253 __u._M_owns = false;
254
255 return *this;
256 }
257
258 void
259 lock()
260 {
261 if (!_M_device)
262 __throw_system_error(int(errc::operation_not_permitted));
263 else if (_M_owns)
264 __throw_system_error(int(errc::resource_deadlock_would_occur));
265 else
266 {
267 _M_device->lock();
268 _M_owns = true;
269 }
270 }
271
272 bool
273 try_lock()
274 {
275 if (!_M_device)
276 __throw_system_error(int(errc::operation_not_permitted));
277 else if (_M_owns)
278 __throw_system_error(int(errc::resource_deadlock_would_occur));
279 else
280 {
281 _M_owns = _M_device->try_lock();
282 return _M_owns;
283 }
284 }
285
286 template<typename _Clock, typename _Duration>
287 bool
288 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
289 {
290 if (!_M_device)
291 __throw_system_error(int(errc::operation_not_permitted));
292 else if (_M_owns)
293 __throw_system_error(int(errc::resource_deadlock_would_occur));
294 else
295 {
296 _M_owns = _M_device->try_lock_until(__atime);
297 return _M_owns;
298 }
299 }
300
301 template<typename _Rep, typename _Period>
302 bool
303 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
304 {
305 if (!_M_device)
306 __throw_system_error(int(errc::operation_not_permitted));
307 else if (_M_owns)
308 __throw_system_error(int(errc::resource_deadlock_would_occur));
309 else
310 {
311 _M_owns = _M_device->try_lock_for(__rtime);
312 return _M_owns;
313 }
314 }
315
316 void
317 unlock()
318 {
319 if (!_M_owns)
320 __throw_system_error(int(errc::operation_not_permitted));
321 else if (_M_device)
322 {
323 _M_device->unlock();
324 _M_owns = false;
325 }
326 }
327
328 void
329 swap(unique_lock& __u) noexcept
330 {
331 std::swap(_M_device, __u._M_device);
332 std::swap(_M_owns, __u._M_owns);
333 }
334
335 mutex_type*
336 release() noexcept
337 {
338 mutex_type* __ret = _M_device;
339 _M_device = 0;
340 _M_owns = false;
341 return __ret;
342 }
343
344 bool
345 owns_lock() const noexcept
346 { return _M_owns; }
347
348 explicit operator bool() const noexcept
349 { return owns_lock(); }
350
351 mutex_type*
352 mutex() const noexcept
353 { return _M_device; }
354
355 private:
356 mutex_type* _M_device;
357 bool _M_owns; // XXX use atomic_bool
358 };
359
360 /// Swap overload for unique_lock objects.
361 template<typename _Mutex>
362 inline void
363 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept
364 { __x.swap(__y); }
365
366 // @} group mutexes
367_GLIBCXX_END_NAMESPACE_VERSION
368} // namespace
369#endif // _GLIBCXX_USE_C99_STDINT_TR1
370
371#endif // C++11
372
373#endif // _GLIBCXX_MUTEX_H

/usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0/bits/gthr-default.h

1/* Threads compatibility routines for libgcc2 and libobjc. */
2/* Compile this one with gcc. */
3/* Copyright (C) 1997-2017 Free Software Foundation, Inc.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
25
26#ifndef _GLIBCXX_GCC_GTHR_POSIX_H
27#define _GLIBCXX_GCC_GTHR_POSIX_H
28
29/* POSIX threads specific definitions.
30 Easy, since the interface is just one-to-one mapping. */
31
32#define __GTHREADS1 1
33#define __GTHREADS_CXX0X1 1
34
35#include <pthread.h>
36
37#if ((defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)) \
38 || !defined(_GTHREAD_USE_MUTEX_TIMEDLOCK1))
39# include <unistd.h>
40# if defined(_POSIX_TIMEOUTS200809L) && _POSIX_TIMEOUTS200809L >= 0
41# define _GTHREAD_USE_MUTEX_TIMEDLOCK1 1
42# else
43# define _GTHREAD_USE_MUTEX_TIMEDLOCK1 0
44# endif
45#endif
46
47typedef pthread_t __gthread_t;
48typedef pthread_key_t __gthread_key_t;
49typedef pthread_once_t __gthread_once_t;
50typedef pthread_mutex_t __gthread_mutex_t;
51typedef pthread_mutex_t __gthread_recursive_mutex_t;
52typedef pthread_cond_t __gthread_cond_t;
53typedef struct timespec __gthread_time_t;
54
55/* POSIX like conditional variables are supported. Please look at comments
56 in gthr.h for details. */
57#define __GTHREAD_HAS_COND1 1
58
59#define __GTHREAD_MUTEX_INIT{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } } PTHREAD_MUTEX_INITIALIZER{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } }
60#define __GTHREAD_MUTEX_INIT_FUNCTION__gthread_mutex_init_function __gthread_mutex_init_function
61#define __GTHREAD_ONCE_INIT0 PTHREAD_ONCE_INIT0
62#if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
63#define __GTHREAD_RECURSIVE_MUTEX_INIT{ { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, 0, { 0, 0 } } } PTHREAD_RECURSIVE_MUTEX_INITIALIZER
64#elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP{ { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, 0, { 0, 0 } } })
65#define __GTHREAD_RECURSIVE_MUTEX_INIT{ { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, 0, { 0, 0 } } } PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP{ { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, 0, { 0, 0 } } }
66#else
67#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
68#endif
69#define __GTHREAD_COND_INIT{ { {0}, {0}, {0, 0}, {0, 0}, 0, 0, {0, 0} } } PTHREAD_COND_INITIALIZER{ { {0}, {0}, {0, 0}, {0, 0}, 0, 0, {0, 0} } }
70#define __GTHREAD_TIME_INIT{0,0} {0,0}
71
72#ifdef _GTHREAD_USE_MUTEX_INIT_FUNC
73# undef __GTHREAD_MUTEX_INIT{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } }
74#endif
75#ifdef _GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC
76# undef __GTHREAD_RECURSIVE_MUTEX_INIT{ { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, 0, { 0, 0 } } }
77# undef __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION
78# define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
79#endif
80#ifdef _GTHREAD_USE_COND_INIT_FUNC
81# undef __GTHREAD_COND_INIT{ { {0}, {0}, {0, 0}, {0, 0}, 0, 0, {0, 0} } }
82# define __GTHREAD_COND_INIT_FUNCTION __gthread_cond_init_function
83#endif
84
85#if __GXX_WEAK__1 && _GLIBCXX_GTHREAD_USE_WEAK1
86# ifndef __gthrw_pragma
87# define __gthrw_pragma(pragma)
88# endif
89# define __gthrw2(name,name2,type)static __typeof(type) name __attribute__ ((__weakref__("name2"
)));
\
90 static __typeof(type) name __attribute__ ((__weakref__(#name2))); \
91 __gthrw_pragma(weak type)
92# define __gthrw_(name)__gthrw_name __gthrw_ ## name
93#else
94# define __gthrw2(name,name2,type)static __typeof(type) name __attribute__ ((__weakref__("name2"
)));
95# define __gthrw_(name)__gthrw_name name
96#endif
97
98/* Typically, __gthrw_foo is a weak reference to symbol foo. */
99#define __gthrw(name)static __typeof(name) __gthrw_name __attribute__ ((__weakref__
("name")));
__gthrw2(__gthrw_ ## name,name,name)static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__
("name")));
100
101__gthrw(pthread_once)static __typeof(pthread_once) __gthrw_pthread_once __attribute__
((__weakref__("pthread_once")));
102__gthrw(pthread_getspecific)static __typeof(pthread_getspecific) __gthrw_pthread_getspecific
__attribute__ ((__weakref__("pthread_getspecific")));
103__gthrw(pthread_setspecific)static __typeof(pthread_setspecific) __gthrw_pthread_setspecific
__attribute__ ((__weakref__("pthread_setspecific")));
104
105__gthrw(pthread_create)static __typeof(pthread_create) __gthrw_pthread_create __attribute__
((__weakref__("pthread_create")));
106__gthrw(pthread_join)static __typeof(pthread_join) __gthrw_pthread_join __attribute__
((__weakref__("pthread_join")));
107__gthrw(pthread_equal)static __typeof(pthread_equal) __gthrw_pthread_equal __attribute__
((__weakref__("pthread_equal")));
108__gthrw(pthread_self)static __typeof(pthread_self) __gthrw_pthread_self __attribute__
((__weakref__("pthread_self")));
109__gthrw(pthread_detach)static __typeof(pthread_detach) __gthrw_pthread_detach __attribute__
((__weakref__("pthread_detach")));
110#ifndef __BIONIC__
111__gthrw(pthread_cancel)static __typeof(pthread_cancel) __gthrw_pthread_cancel __attribute__
((__weakref__("pthread_cancel")));
112#endif
113__gthrw(sched_yield)static __typeof(sched_yield) __gthrw_sched_yield __attribute__
((__weakref__("sched_yield")));
114
115__gthrw(pthread_mutex_lock)static __typeof(pthread_mutex_lock) __gthrw_pthread_mutex_lock
__attribute__ ((__weakref__("pthread_mutex_lock")));
116__gthrw(pthread_mutex_trylock)static __typeof(pthread_mutex_trylock) __gthrw_pthread_mutex_trylock
__attribute__ ((__weakref__("pthread_mutex_trylock")));
117#if _GTHREAD_USE_MUTEX_TIMEDLOCK1
118__gthrw(pthread_mutex_timedlock)static __typeof(pthread_mutex_timedlock) __gthrw_pthread_mutex_timedlock
__attribute__ ((__weakref__("pthread_mutex_timedlock")));
119#endif
120__gthrw(pthread_mutex_unlock)static __typeof(pthread_mutex_unlock) __gthrw_pthread_mutex_unlock
__attribute__ ((__weakref__("pthread_mutex_unlock")));
121__gthrw(pthread_mutex_init)static __typeof(pthread_mutex_init) __gthrw_pthread_mutex_init
__attribute__ ((__weakref__("pthread_mutex_init")));
122__gthrw(pthread_mutex_destroy)static __typeof(pthread_mutex_destroy) __gthrw_pthread_mutex_destroy
__attribute__ ((__weakref__("pthread_mutex_destroy")));
123
124__gthrw(pthread_cond_init)static __typeof(pthread_cond_init) __gthrw_pthread_cond_init __attribute__
((__weakref__("pthread_cond_init")));
125__gthrw(pthread_cond_broadcast)static __typeof(pthread_cond_broadcast) __gthrw_pthread_cond_broadcast
__attribute__ ((__weakref__("pthread_cond_broadcast")));
126__gthrw(pthread_cond_signal)static __typeof(pthread_cond_signal) __gthrw_pthread_cond_signal
__attribute__ ((__weakref__("pthread_cond_signal")));
127__gthrw(pthread_cond_wait)static __typeof(pthread_cond_wait) __gthrw_pthread_cond_wait __attribute__
((__weakref__("pthread_cond_wait")));
128__gthrw(pthread_cond_timedwait)static __typeof(pthread_cond_timedwait) __gthrw_pthread_cond_timedwait
__attribute__ ((__weakref__("pthread_cond_timedwait")));
129__gthrw(pthread_cond_destroy)static __typeof(pthread_cond_destroy) __gthrw_pthread_cond_destroy
__attribute__ ((__weakref__("pthread_cond_destroy")));
130
131__gthrw(pthread_key_create)static __typeof(pthread_key_create) __gthrw_pthread_key_create
__attribute__ ((__weakref__("pthread_key_create")));
132__gthrw(pthread_key_delete)static __typeof(pthread_key_delete) __gthrw_pthread_key_delete
__attribute__ ((__weakref__("pthread_key_delete")));
133__gthrw(pthread_mutexattr_init)static __typeof(pthread_mutexattr_init) __gthrw_pthread_mutexattr_init
__attribute__ ((__weakref__("pthread_mutexattr_init")));
134__gthrw(pthread_mutexattr_settype)static __typeof(pthread_mutexattr_settype) __gthrw_pthread_mutexattr_settype
__attribute__ ((__weakref__("pthread_mutexattr_settype")));
135__gthrw(pthread_mutexattr_destroy)static __typeof(pthread_mutexattr_destroy) __gthrw_pthread_mutexattr_destroy
__attribute__ ((__weakref__("pthread_mutexattr_destroy")));
136
137
138#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
139/* Objective-C. */
140__gthrw(pthread_exit)static __typeof(pthread_exit) __gthrw_pthread_exit __attribute__
((__weakref__("pthread_exit")));
141#ifdef _POSIX_PRIORITY_SCHEDULING200809L
142#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING200809L
143__gthrw(sched_get_priority_max)static __typeof(sched_get_priority_max) __gthrw_sched_get_priority_max
__attribute__ ((__weakref__("sched_get_priority_max")));
144__gthrw(sched_get_priority_min)static __typeof(sched_get_priority_min) __gthrw_sched_get_priority_min
__attribute__ ((__weakref__("sched_get_priority_min")));
145#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
146#endif /* _POSIX_PRIORITY_SCHEDULING */
147__gthrw(pthread_attr_destroy)static __typeof(pthread_attr_destroy) __gthrw_pthread_attr_destroy
__attribute__ ((__weakref__("pthread_attr_destroy")));
148__gthrw(pthread_attr_init)static __typeof(pthread_attr_init) __gthrw_pthread_attr_init __attribute__
((__weakref__("pthread_attr_init")));
149__gthrw(pthread_attr_setdetachstate)static __typeof(pthread_attr_setdetachstate) __gthrw_pthread_attr_setdetachstate
__attribute__ ((__weakref__("pthread_attr_setdetachstate")))
;
150#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING200809L
151__gthrw(pthread_getschedparam)static __typeof(pthread_getschedparam) __gthrw_pthread_getschedparam
__attribute__ ((__weakref__("pthread_getschedparam")));
152__gthrw(pthread_setschedparam)static __typeof(pthread_setschedparam) __gthrw_pthread_setschedparam
__attribute__ ((__weakref__("pthread_setschedparam")));
153#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
154#endif /* _LIBOBJC || _LIBOBJC_WEAK */
155
156#if __GXX_WEAK__1 && _GLIBCXX_GTHREAD_USE_WEAK1
157
158/* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
159 -pthreads is not specified. The functions are dummies and most return an
160 error value. However pthread_once returns 0 without invoking the routine
161 it is passed so we cannot pretend that the interface is active if -pthreads
162 is not specified. On Solaris 2.5.1, the interface is not exposed at all so
163 we need to play the usual game with weak symbols. On Solaris 10 and up, a
164 working interface is always exposed. On FreeBSD 6 and later, libc also
165 exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up
166 to 9 does. FreeBSD >= 700014 even provides a pthread_cancel stub in libc,
167 which means the alternate __gthread_active_p below cannot be used there. */
168
169#if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
170
171static volatile int __gthread_active = -1;
172
173static void
174__gthread_trigger (void)
175{
176 __gthread_active = 1;
177}
178
179static inline int
180__gthread_active_p (void)
181{
182 static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } };
183 static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT0;
184
185 /* Avoid reading __gthread_active twice on the main code path. */
186 int __gthread_active_latest_value = __gthread_active;
187
188 /* This test is not protected to avoid taking a lock on the main code
189 path so every update of __gthread_active in a threaded program must
190 be atomic with regard to the result of the test. */
191 if (__builtin_expect (__gthread_active_latest_value < 0, 0))
192 {
193 if (__gthrw_(pthread_once)__gthrw_pthread_once)
194 {
195 /* If this really is a threaded program, then we must ensure that
196 __gthread_active has been set to 1 before exiting this block. */
197 __gthrw_(pthread_mutex_lock)__gthrw_pthread_mutex_lock (&__gthread_active_mutex);
198 __gthrw_(pthread_once)__gthrw_pthread_once (&__gthread_active_once, __gthread_trigger);
199 __gthrw_(pthread_mutex_unlock)__gthrw_pthread_mutex_unlock (&__gthread_active_mutex);
200 }
201
202 /* Make sure we'll never enter this block again. */
203 if (__gthread_active < 0)
204 __gthread_active = 0;
205
206 __gthread_active_latest_value = __gthread_active;
207 }
208
209 return __gthread_active_latest_value != 0;
210}
211
212#else /* neither FreeBSD nor Solaris */
213
214/* For a program to be multi-threaded the only thing that it certainly must
215 be using is pthread_create. However, there may be other libraries that
216 intercept pthread_create with their own definitions to wrap pthreads
217 functionality for some purpose. In those cases, pthread_create being
218 defined might not necessarily mean that libpthread is actually linked
219 in.
220
221 For the GNU C library, we can use a known internal name. This is always
222 available in the ABI, but no other library would define it. That is
223 ideal, since any public pthread function might be intercepted just as
224 pthread_create might be. __pthread_key_create is an "internal"
225 implementation symbol, but it is part of the public exported ABI. Also,
226 it's among the symbols that the static libpthread.a always links in
227 whenever pthread_create is used, so there is no danger of a false
228 negative result in any statically-linked, multi-threaded program.
229
230 For others, we choose pthread_cancel as a function that seems unlikely
231 to be redefined by an interceptor library. The bionic (Android) C
232 library does not provide pthread_cancel, so we do use pthread_create
233 there (and interceptor libraries lose). */
234
235#ifdef __GLIBC__2
236__gthrw2(__gthrw_(__pthread_key_create),static __typeof(pthread_key_create) __gthrw___pthread_key_create
__attribute__ ((__weakref__("__pthread_key_create")));
237 __pthread_key_create,static __typeof(pthread_key_create) __gthrw___pthread_key_create
__attribute__ ((__weakref__("__pthread_key_create")));
238 pthread_key_create)static __typeof(pthread_key_create) __gthrw___pthread_key_create
__attribute__ ((__weakref__("__pthread_key_create")));
239# define GTHR_ACTIVE_PROXY__gthrw___pthread_key_create __gthrw_(__pthread_key_create)__gthrw___pthread_key_create
240#elif defined (__BIONIC__)
241# define GTHR_ACTIVE_PROXY__gthrw___pthread_key_create __gthrw_(pthread_create)__gthrw_pthread_create
242#else
243# define GTHR_ACTIVE_PROXY__gthrw___pthread_key_create __gthrw_(pthread_cancel)__gthrw_pthread_cancel
244#endif
245
246static inline int
247__gthread_active_p (void)
248{
249 static void *const __gthread_active_ptr
250 = __extension__ (void *) &GTHR_ACTIVE_PROXY__gthrw___pthread_key_create;
251 return __gthread_active_ptr != 0;
252}
253
254#endif /* FreeBSD or Solaris */
255
256#else /* not __GXX_WEAK__ */
257
258/* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread
259 calls in shared flavors of the HP-UX C library. Most of the stubs
260 have no functionality. The details are described in the "libc cumulative
261 patch" for each subversion of HP-UX 11. There are two special interfaces
262 provided for checking whether an application is linked to a shared pthread
263 library or not. However, these interfaces aren't available in early
264 libpthread libraries. We also need a test that works for archive
265 libraries. We can't use pthread_once as some libc versions call the
266 init function. We also can't use pthread_create or pthread_attr_init
267 as these create a thread and thereby prevent changing the default stack
268 size. The function pthread_default_stacksize_np is available in both
269 the archive and shared versions of libpthread. It can be used to
270 determine the default pthread stack size. There is a stub in some
271 shared libc versions which returns a zero size if pthreads are not
272 active. We provide an equivalent stub to handle cases where libc
273 doesn't provide one. */
274
275#if defined(__hppa__) && defined(__hpux__)
276
277static volatile int __gthread_active = -1;
278
279static inline int
280__gthread_active_p (void)
281{
282 /* Avoid reading __gthread_active twice on the main code path. */
283 int __gthread_active_latest_value = __gthread_active;
284 size_t __s;
285
286 if (__builtin_expect (__gthread_active_latest_value < 0, 0))
287 {
288 pthread_default_stacksize_np (0, &__s);
289 __gthread_active = __s ? 1 : 0;
290 __gthread_active_latest_value = __gthread_active;
291 }
292
293 return __gthread_active_latest_value != 0;
294}
295
296#else /* not hppa-hpux */
297
298static inline int
299__gthread_active_p (void)
300{
301 return 1;
302}
303
304#endif /* hppa-hpux */
305
306#endif /* __GXX_WEAK__ */
307
308#ifdef _LIBOBJC
309
310/* This is the config.h file in libobjc/ */
311#include <config.h>
312
313#ifdef HAVE_SCHED_H
314# include <sched.h>
315#endif
316
317/* Key structure for maintaining thread specific storage */
318static pthread_key_t _objc_thread_storage;
319static pthread_attr_t _objc_thread_attribs;
320
321/* Thread local storage for a single thread */
322static void *thread_local_storage = NULL__null;
323
324/* Backend initialization functions */
325
326/* Initialize the threads subsystem. */
327static inline int
328__gthread_objc_init_thread_system (void)
329{
330 if (__gthread_active_p ())
331 {
332 /* Initialize the thread storage key. */
333 if (__gthrw_(pthread_key_create)__gthrw_pthread_key_create (&_objc_thread_storage, NULL__null) == 0)
334 {
335 /* The normal default detach state for threads is
336 * PTHREAD_CREATE_JOINABLE which causes threads to not die
337 * when you think they should. */
338 if (__gthrw_(pthread_attr_init)__gthrw_pthread_attr_init (&_objc_thread_attribs) == 0
339 && __gthrw_(pthread_attr_setdetachstate)__gthrw_pthread_attr_setdetachstate (&_objc_thread_attribs,
340 PTHREAD_CREATE_DETACHEDPTHREAD_CREATE_DETACHED) == 0)
341 return 0;
342 }
343 }
344
345 return -1;
346}
347
348/* Close the threads subsystem. */
349static inline int
350__gthread_objc_close_thread_system (void)
351{
352 if (__gthread_active_p ()
353 && __gthrw_(pthread_key_delete)__gthrw_pthread_key_delete (_objc_thread_storage) == 0
354 && __gthrw_(pthread_attr_destroy)__gthrw_pthread_attr_destroy (&_objc_thread_attribs) == 0)
355 return 0;
356
357 return -1;
358}
359
360/* Backend thread functions */
361
362/* Create a new thread of execution. */
363static inline objc_thread_t
364__gthread_objc_thread_detach (void (*func)(void *), void *arg)
365{
366 objc_thread_t thread_id;
367 pthread_t new_thread_handle;
368
369 if (!__gthread_active_p ())
370 return NULL__null;
371
372 if (!(__gthrw_(pthread_create)__gthrw_pthread_create (&new_thread_handle, &_objc_thread_attribs,
373 (void *) func, arg)))
374 thread_id = (objc_thread_t) new_thread_handle;
375 else
376 thread_id = NULL__null;
377
378 return thread_id;
379}
380
381/* Set the current thread's priority. */
382static inline int
383__gthread_objc_thread_set_priority (int priority)
384{
385 if (!__gthread_active_p ())
386 return -1;
387 else
388 {
389#ifdef _POSIX_PRIORITY_SCHEDULING200809L
390#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING200809L
391 pthread_t thread_id = __gthrw_(pthread_self)__gthrw_pthread_self ();
392 int policy;
393 struct sched_param params;
394 int priority_min, priority_max;
395
396 if (__gthrw_(pthread_getschedparam)__gthrw_pthread_getschedparam (thread_id, &policy, &params) == 0)
397 {
398 if ((priority_max = __gthrw_(sched_get_priority_max)__gthrw_sched_get_priority_max (policy)) == -1)
399 return -1;
400
401 if ((priority_min = __gthrw_(sched_get_priority_min)__gthrw_sched_get_priority_min (policy)) == -1)
402 return -1;
403
404 if (priority > priority_max)
405 priority = priority_max;
406 else if (priority < priority_min)
407 priority = priority_min;
408 params.sched_prioritysched_priority = priority;
409
410 /*
411 * The solaris 7 and several other man pages incorrectly state that
412 * this should be a pointer to policy but pthread.h is universally
413 * at odds with this.
414 */
415 if (__gthrw_(pthread_setschedparam)__gthrw_pthread_setschedparam (thread_id, policy, &params) == 0)
416 return 0;
417 }
418#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
419#endif /* _POSIX_PRIORITY_SCHEDULING */
420 return -1;
421 }
422}
423
424/* Return the current thread's priority. */
425static inline int
426__gthread_objc_thread_get_priority (void)
427{
428#ifdef _POSIX_PRIORITY_SCHEDULING200809L
429#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING200809L
430 if (__gthread_active_p ())
431 {
432 int policy;
433 struct sched_param params;
434
435 if (__gthrw_(pthread_getschedparam)__gthrw_pthread_getschedparam (__gthrw_(pthread_self)__gthrw_pthread_self (), &policy, &params) == 0)
436 return params.sched_prioritysched_priority;
437 else
438 return -1;
439 }
440 else
441#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
442#endif /* _POSIX_PRIORITY_SCHEDULING */
443 return OBJC_THREAD_INTERACTIVE_PRIORITY;
444}
445
446/* Yield our process time to another thread. */
447static inline void
448__gthread_objc_thread_yield (void)
449{
450 if (__gthread_active_p ())
451 __gthrw_(sched_yield)__gthrw_sched_yield ();
452}
453
454/* Terminate the current thread. */
455static inline int
456__gthread_objc_thread_exit (void)
457{
458 if (__gthread_active_p ())
459 /* exit the thread */
460 __gthrw_(pthread_exit)__gthrw_pthread_exit (&__objc_thread_exit_status);
461
462 /* Failed if we reached here */
463 return -1;
464}
465
466/* Returns an integer value which uniquely describes a thread. */
467static inline objc_thread_t
468__gthread_objc_thread_id (void)
469{
470 if (__gthread_active_p ())
471 return (objc_thread_t) __gthrw_(pthread_self)__gthrw_pthread_self ();
472 else
473 return (objc_thread_t) 1;
474}
475
476/* Sets the thread's local storage pointer. */
477static inline int
478__gthread_objc_thread_set_data (void *value)
479{
480 if (__gthread_active_p ())
481 return __gthrw_(pthread_setspecific)__gthrw_pthread_setspecific (_objc_thread_storage, value);
482 else
483 {
484 thread_local_storage = value;
485 return 0;
486 }
487}
488
489/* Returns the thread's local storage pointer. */
490static inline void *
491__gthread_objc_thread_get_data (void)
492{
493 if (__gthread_active_p ())
494 return __gthrw_(pthread_getspecific)__gthrw_pthread_getspecific (_objc_thread_storage);
495 else
496 return thread_local_storage;
497}
498
499/* Backend mutex functions */
500
501/* Allocate a mutex. */
502static inline int
503__gthread_objc_mutex_allocate (objc_mutex_t mutex)
504{
505 if (__gthread_active_p ())
506 {
507 mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
508
509 if (__gthrw_(pthread_mutex_init)__gthrw_pthread_mutex_init ((pthread_mutex_t *) mutex->backend, NULL__null))
510 {
511 objc_free (mutex->backend);
512 mutex->backend = NULL__null;
513 return -1;
514 }
515 }
516
517 return 0;
518}
519
520/* Deallocate a mutex. */
521static inline int
522__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
523{
524 if (__gthread_active_p ())
525 {
526 int count;
527
528 /*
529 * Posix Threads specifically require that the thread be unlocked
530 * for __gthrw_(pthread_mutex_destroy) to work.
531 */
532
533 do
534 {
535 count = __gthrw_(pthread_mutex_unlock)__gthrw_pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend);
536 if (count < 0)
537 return -1;
538 }
539 while (count);
540
541 if (__gthrw_(pthread_mutex_destroy)__gthrw_pthread_mutex_destroy ((pthread_mutex_t *) mutex->backend))
542 return -1;
543
544 objc_free (mutex->backend);
545 mutex->backend = NULL__null;
546 }
547 return 0;
548}
549
550/* Grab a lock on a mutex. */
551static inline int
552__gthread_objc_mutex_lock (objc_mutex_t mutex)
553{
554 if (__gthread_active_p ()
555 && __gthrw_(pthread_mutex_lock)__gthrw_pthread_mutex_lock ((pthread_mutex_t *) mutex->backend) != 0)
556 {
557 return -1;
558 }
559
560 return 0;
561}
562
563/* Try to grab a lock on a mutex. */
564static inline int
565__gthread_objc_mutex_trylock (objc_mutex_t mutex)
566{
567 if (__gthread_active_p ()
568 && __gthrw_(pthread_mutex_trylock)__gthrw_pthread_mutex_trylock ((pthread_mutex_t *) mutex->backend) != 0)
569 {
570 return -1;
571 }
572
573 return 0;
574}
575
576/* Unlock the mutex */
577static inline int
578__gthread_objc_mutex_unlock (objc_mutex_t mutex)
579{
580 if (__gthread_active_p ()
581 && __gthrw_(pthread_mutex_unlock)__gthrw_pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend) != 0)
582 {
583 return -1;
584 }
585
586 return 0;
587}
588
589/* Backend condition mutex functions */
590
591/* Allocate a condition. */
592static inline int
593__gthread_objc_condition_allocate (objc_condition_t condition)
594{
595 if (__gthread_active_p ())
596 {
597 condition->backend = objc_malloc (sizeof (pthread_cond_t));
598
599 if (__gthrw_(pthread_cond_init)__gthrw_pthread_cond_init ((pthread_cond_t *) condition->backend, NULL__null))
600 {
601 objc_free (condition->backend);
602 condition->backend = NULL__null;
603 return -1;
604 }
605 }
606
607 return 0;
608}
609
610/* Deallocate a condition. */
611static inline int
612__gthread_objc_condition_deallocate (objc_condition_t condition)
613{
614 if (__gthread_active_p ())
615 {
616 if (__gthrw_(pthread_cond_destroy)__gthrw_pthread_cond_destroy ((pthread_cond_t *) condition->backend))
617 return -1;
618
619 objc_free (condition->backend);
620 condition->backend = NULL__null;
621 }
622 return 0;
623}
624
625/* Wait on the condition */
626static inline int
627__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
628{
629 if (__gthread_active_p ())
630 return __gthrw_(pthread_cond_wait)__gthrw_pthread_cond_wait ((pthread_cond_t *) condition->backend,
631 (pthread_mutex_t *) mutex->backend);
632 else
633 return 0;
634}
635
636/* Wake up all threads waiting on this condition. */
637static inline int
638__gthread_objc_condition_broadcast (objc_condition_t condition)
639{
640 if (__gthread_active_p ())
641 return __gthrw_(pthread_cond_broadcast)__gthrw_pthread_cond_broadcast ((pthread_cond_t *) condition->backend);
642 else
643 return 0;
644}
645
646/* Wake up one thread waiting on this condition. */
647static inline int
648__gthread_objc_condition_signal (objc_condition_t condition)
649{
650 if (__gthread_active_p ())
651 return __gthrw_(pthread_cond_signal)__gthrw_pthread_cond_signal ((pthread_cond_t *) condition->backend);
652 else
653 return 0;
654}
655
656#else /* _LIBOBJC */
657
658static inline int
659__gthread_create (__gthread_t *__threadid, void *(*__func) (void*),
660 void *__args)
661{
662 return __gthrw_(pthread_create)__gthrw_pthread_create (__threadid, NULL__null, __func, __args);
663}
664
665static inline int
666__gthread_join (__gthread_t __threadid, void **__value_ptr)
667{
668 return __gthrw_(pthread_join)__gthrw_pthread_join (__threadid, __value_ptr);
669}
670
671static inline int
672__gthread_detach (__gthread_t __threadid)
673{
674 return __gthrw_(pthread_detach)__gthrw_pthread_detach (__threadid);
675}
676
677static inline int
678__gthread_equal (__gthread_t __t1, __gthread_t __t2)
679{
680 return __gthrw_(pthread_equal)__gthrw_pthread_equal (__t1, __t2);
681}
682
683static inline __gthread_t
684__gthread_self (void)
685{
686 return __gthrw_(pthread_self)__gthrw_pthread_self ();
687}
688
689static inline int
690__gthread_yield (void)
691{
692 return __gthrw_(sched_yield)__gthrw_sched_yield ();
693}
694
695static inline int
696__gthread_once (__gthread_once_t *__once, void (*__func) (void))
697{
698 if (__gthread_active_p ())
699 return __gthrw_(pthread_once)__gthrw_pthread_once (__once, __func);
700 else
701 return -1;
702}
703
704static inline int
705__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
706{
707 return __gthrw_(pthread_key_create)__gthrw_pthread_key_create (__key, __dtor);
708}
709
710static inline int
711__gthread_key_delete (__gthread_key_t __key)
712{
713 return __gthrw_(pthread_key_delete)__gthrw_pthread_key_delete (__key);
714}
715
716static inline void *
717__gthread_getspecific (__gthread_key_t __key)
718{
719 return __gthrw_(pthread_getspecific)__gthrw_pthread_getspecific (__key);
720}
721
722static inline int
723__gthread_setspecific (__gthread_key_t __key, const void *__ptr)
724{
725 return __gthrw_(pthread_setspecific)__gthrw_pthread_setspecific (__key, __ptr);
726}
727
728static inline void
729__gthread_mutex_init_function (__gthread_mutex_t *__mutex)
730{
731 if (__gthread_active_p ())
732 __gthrw_(pthread_mutex_init)__gthrw_pthread_mutex_init (__mutex, NULL__null);
733}
734
735static inline int
736__gthread_mutex_destroy (__gthread_mutex_t *__mutex)
737{
738 if (__gthread_active_p ())
739 return __gthrw_(pthread_mutex_destroy)__gthrw_pthread_mutex_destroy (__mutex);
740 else
741 return 0;
742}
743
744static inline int
745__gthread_mutex_lock (__gthread_mutex_t *__mutex)
746{
747 if (__gthread_active_p ())
11
Assuming the condition is false
12
Taking false branch
748 return __gthrw_(pthread_mutex_lock)__gthrw_pthread_mutex_lock (__mutex);
749 else
750 return 0;
751}
752
753static inline int
754__gthread_mutex_trylock (__gthread_mutex_t *__mutex)
755{
756 if (__gthread_active_p ())
757 return __gthrw_(pthread_mutex_trylock)__gthrw_pthread_mutex_trylock (__mutex);
758 else
759 return 0;
760}
761
762#if _GTHREAD_USE_MUTEX_TIMEDLOCK1
763static inline int
764__gthread_mutex_timedlock (__gthread_mutex_t *__mutex,
765 const __gthread_time_t *__abs_timeout)
766{
767 if (__gthread_active_p ())
768 return __gthrw_(pthread_mutex_timedlock)__gthrw_pthread_mutex_timedlock (__mutex, __abs_timeout);
769 else
770 return 0;
771}
772#endif
773
774static inline int
775__gthread_mutex_unlock (__gthread_mutex_t *__mutex)
776{
777 if (__gthread_active_p ())
778 return __gthrw_(pthread_mutex_unlock)__gthrw_pthread_mutex_unlock (__mutex);
779 else
780 return 0;
781}
782
783#if !defined( PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP{ { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, 0, { 0, 0 } } }) \
784 || defined(_GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC)
785static inline int
786__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
787{
788 if (__gthread_active_p ())
789 {
790 pthread_mutexattr_t __attr;
791 int __r;
792
793 __r = __gthrw_(pthread_mutexattr_init)__gthrw_pthread_mutexattr_init (&__attr);
794 if (!__r)
795 __r = __gthrw_(pthread_mutexattr_settype)__gthrw_pthread_mutexattr_settype (&__attr,
796 PTHREAD_MUTEX_RECURSIVE);
797 if (!__r)
798 __r = __gthrw_(pthread_mutex_init)__gthrw_pthread_mutex_init (__mutex, &__attr);
799 if (!__r)
800 __r = __gthrw_(pthread_mutexattr_destroy)__gthrw_pthread_mutexattr_destroy (&__attr);
801 return __r;
802 }
803 return 0;
804}
805#endif
806
807static inline int
808__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
809{
810 return __gthread_mutex_lock (__mutex);
811}
812
813static inline int
814__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
815{
816 return __gthread_mutex_trylock (__mutex);
817}
818
819#if _GTHREAD_USE_MUTEX_TIMEDLOCK1
820static inline int
821__gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex,
822 const __gthread_time_t *__abs_timeout)
823{
824 return __gthread_mutex_timedlock (__mutex, __abs_timeout);
825}
826#endif
827
828static inline int
829__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
830{
831 return __gthread_mutex_unlock (__mutex);
832}
833
834static inline int
835__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
836{
837 return __gthread_mutex_destroy (__mutex);
838}
839
840#ifdef _GTHREAD_USE_COND_INIT_FUNC
841static inline void
842__gthread_cond_init_function (__gthread_cond_t *__cond)
843{
844 if (__gthread_active_p ())
845 __gthrw_(pthread_cond_init)__gthrw_pthread_cond_init (__cond, NULL__null);
846}
847#endif
848
849static inline int
850__gthread_cond_broadcast (__gthread_cond_t *__cond)
851{
852 return __gthrw_(pthread_cond_broadcast)__gthrw_pthread_cond_broadcast (__cond);
853}
854
855static inline int
856__gthread_cond_signal (__gthread_cond_t *__cond)
857{
858 return __gthrw_(pthread_cond_signal)__gthrw_pthread_cond_signal (__cond);
859}
860
861static inline int
862__gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
863{
864 return __gthrw_(pthread_cond_wait)__gthrw_pthread_cond_wait (__cond, __mutex);
865}
866
867static inline int
868__gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex,
869 const __gthread_time_t *__abs_timeout)
870{
871 return __gthrw_(pthread_cond_timedwait)__gthrw_pthread_cond_timedwait (__cond, __mutex, __abs_timeout);
872}
873
874static inline int
875__gthread_cond_wait_recursive (__gthread_cond_t *__cond,
876 __gthread_recursive_mutex_t *__mutex)
877{
878 return __gthread_cond_wait (__cond, __mutex);
879}
880
881static inline int
882__gthread_cond_destroy (__gthread_cond_t* __cond)
883{
884 return __gthrw_(pthread_cond_destroy)__gthrw_pthread_cond_destroy (__cond);
885}
886
887#endif /* _LIBOBJC */
888
889#endif /* ! _GLIBCXX_GCC_GTHR_POSIX_H */

/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCSerialization.h

1//===- llvm/ExecutionEngine/Orc/RPCSerialization.h --------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H
11#define LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H
12
13#include "OrcError.h"
14#include "llvm/Support/thread.h"
15#include <map>
16#include <mutex>
17#include <sstream>
18
19namespace llvm {
20namespace orc {
21namespace rpc {
22
23template <typename T>
24class RPCTypeName;
25
26/// TypeNameSequence is a utility for rendering sequences of types to a string
27/// by rendering each type, separated by ", ".
28template <typename... ArgTs> class RPCTypeNameSequence {};
29
30/// Render an empty TypeNameSequence to an ostream.
31template <typename OStream>
32OStream &operator<<(OStream &OS, const RPCTypeNameSequence<> &V) {
33 return OS;
34}
35
36/// Render a TypeNameSequence of a single type to an ostream.
37template <typename OStream, typename ArgT>
38OStream &operator<<(OStream &OS, const RPCTypeNameSequence<ArgT> &V) {
39 OS << RPCTypeName<ArgT>::getName();
40 return OS;
41}
42
43/// Render a TypeNameSequence of more than one type to an ostream.
44template <typename OStream, typename ArgT1, typename ArgT2, typename... ArgTs>
45OStream&
46operator<<(OStream &OS, const RPCTypeNameSequence<ArgT1, ArgT2, ArgTs...> &V) {
47 OS << RPCTypeName<ArgT1>::getName() << ", "
48 << RPCTypeNameSequence<ArgT2, ArgTs...>();
49 return OS;
50}
51
52template <>
53class RPCTypeName<void> {
54public:
55 static const char* getName() { return "void"; }
56};
57
58template <>
59class RPCTypeName<int8_t> {
60public:
61 static const char* getName() { return "int8_t"; }
62};
63
64template <>
65class RPCTypeName<uint8_t> {
66public:
67 static const char* getName() { return "uint8_t"; }
68};
69
70template <>
71class RPCTypeName<int16_t> {
72public:
73 static const char* getName() { return "int16_t"; }
74};
75
76template <>
77class RPCTypeName<uint16_t> {
78public:
79 static const char* getName() { return "uint16_t"; }
80};
81
82template <>
83class RPCTypeName<int32_t> {
84public:
85 static const char* getName() { return "int32_t"; }
86};
87
88template <>
89class RPCTypeName<uint32_t> {
90public:
91 static const char* getName() { return "uint32_t"; }
92};
93
94template <>
95class RPCTypeName<int64_t> {
96public:
97 static const char* getName() { return "int64_t"; }
98};
99
100template <>
101class RPCTypeName<uint64_t> {
102public:
103 static const char* getName() { return "uint64_t"; }
104};
105
106template <>
107class RPCTypeName<bool> {
108public:
109 static const char* getName() { return "bool"; }
110};
111
112template <>
113class RPCTypeName<std::string> {
114public:
115 static const char* getName() { return "std::string"; }
116};
117
118template <>
119class RPCTypeName<Error> {
120public:
121 static const char* getName() { return "Error"; }
122};
123
124template <typename T>
125class RPCTypeName<Expected<T>> {
126public:
127 static const char* getName() {
128 std::lock_guard<std::mutex> Lock(NameMutex);
129 if (Name.empty())
130 raw_string_ostream(Name) << "Expected<"
131 << RPCTypeNameSequence<T>()
132 << ">";
133 return Name.data();
134 }
135
136private:
137 static std::mutex NameMutex;
138 static std::string Name;
139};
140
141template <typename T>
142std::mutex RPCTypeName<Expected<T>>::NameMutex;
143
144template <typename T>
145std::string RPCTypeName<Expected<T>>::Name;
146
147template <typename T1, typename T2>
148class RPCTypeName<std::pair<T1, T2>> {
149public:
150 static const char* getName() {
151 std::lock_guard<std::mutex> Lock(NameMutex);
152 if (Name.empty())
153 raw_string_ostream(Name) << "std::pair<" << RPCTypeNameSequence<T1, T2>()
154 << ">";
155 return Name.data();
156 }
157private:
158 static std::mutex NameMutex;
159 static std::string Name;
160};
161
162template <typename T1, typename T2>
163std::mutex RPCTypeName<std::pair<T1, T2>>::NameMutex;
164template <typename T1, typename T2>
165std::string RPCTypeName<std::pair<T1, T2>>::Name;
166
167template <typename... ArgTs>
168class RPCTypeName<std::tuple<ArgTs...>> {
169public:
170 static const char* getName() {
171 std::lock_guard<std::mutex> Lock(NameMutex);
172 if (Name.empty())
173 raw_string_ostream(Name) << "std::tuple<"
174 << RPCTypeNameSequence<ArgTs...>() << ">";
175 return Name.data();
176 }
177private:
178 static std::mutex NameMutex;
179 static std::string Name;
180};
181
182template <typename... ArgTs>
183std::mutex RPCTypeName<std::tuple<ArgTs...>>::NameMutex;
184template <typename... ArgTs>
185std::string RPCTypeName<std::tuple<ArgTs...>>::Name;
186
187template <typename T>
188class RPCTypeName<std::vector<T>> {
189public:
190 static const char*getName() {
191 std::lock_guard<std::mutex> Lock(NameMutex);
192 if (Name.empty())
193 raw_string_ostream(Name) << "std::vector<" << RPCTypeName<T>::getName()
194 << ">";
195 return Name.data();
196 }
197
198private:
199 static std::mutex NameMutex;
200 static std::string Name;
201};
202
203template <typename T>
204std::mutex RPCTypeName<std::vector<T>>::NameMutex;
205template <typename T>
206std::string RPCTypeName<std::vector<T>>::Name;
207
208
209/// The SerializationTraits<ChannelT, T> class describes how to serialize and
210/// deserialize an instance of type T to/from an abstract channel of type
211/// ChannelT. It also provides a representation of the type's name via the
212/// getName method.
213///
214/// Specializations of this class should provide the following functions:
215///
216/// @code{.cpp}
217///
218/// static const char* getName();
219/// static Error serialize(ChannelT&, const T&);
220/// static Error deserialize(ChannelT&, T&);
221///
222/// @endcode
223///
224/// The third argument of SerializationTraits is intended to support SFINAE.
225/// E.g.:
226///
227/// @code{.cpp}
228///
229/// class MyVirtualChannel { ... };
230///
231/// template <DerivedChannelT>
232/// class SerializationTraits<DerivedChannelT, bool,
233/// typename std::enable_if<
234/// std::is_base_of<VirtChannel, DerivedChannel>::value
235/// >::type> {
236/// public:
237/// static const char* getName() { ... };
238/// }
239///
240/// @endcode
241template <typename ChannelT, typename WireType,
242 typename ConcreteType = WireType, typename = void>
243class SerializationTraits;
244
245template <typename ChannelT>
246class SequenceTraits {
247public:
248 static Error emitSeparator(ChannelT &C) { return Error::success(); }
249 static Error consumeSeparator(ChannelT &C) { return Error::success(); }
250};
251
252/// Utility class for serializing sequences of values of varying types.
253/// Specializations of this class contain 'serialize' and 'deserialize' methods
254/// for the given channel. The ArgTs... list will determine the "over-the-wire"
255/// types to be serialized. The serialize and deserialize methods take a list
256/// CArgTs... ("caller arg types") which must be the same length as ArgTs...,
257/// but may be different types from ArgTs, provided that for each CArgT there
258/// is a SerializationTraits specialization
259/// SerializeTraits<ChannelT, ArgT, CArgT> with methods that can serialize the
260/// caller argument to over-the-wire value.
261template <typename ChannelT, typename... ArgTs>
262class SequenceSerialization;
263
264template <typename ChannelT>
265class SequenceSerialization<ChannelT> {
266public:
267 static Error serialize(ChannelT &C) { return Error::success(); }
268 static Error deserialize(ChannelT &C) { return Error::success(); }
269};
270
271template <typename ChannelT, typename ArgT>
272class SequenceSerialization<ChannelT, ArgT> {
273public:
274
275 template <typename CArgT>
276 static Error serialize(ChannelT &C, CArgT &&CArg) {
277 return SerializationTraits<ChannelT, ArgT,
278 typename std::decay<CArgT>::type>::
279 serialize(C, std::forward<CArgT>(CArg));
280 }
281
282 template <typename CArgT>
283 static Error deserialize(ChannelT &C, CArgT &CArg) {
284 return SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg);
285 }
286};
287
288template <typename ChannelT, typename ArgT, typename... ArgTs>
289class SequenceSerialization<ChannelT, ArgT, ArgTs...> {
290public:
291
292 template <typename CArgT, typename... CArgTs>
293 static Error serialize(ChannelT &C, CArgT &&CArg,
294 CArgTs &&... CArgs) {
295 if (auto Err =
296 SerializationTraits<ChannelT, ArgT, typename std::decay<CArgT>::type>::
297 serialize(C, std::forward<CArgT>(CArg)))
298 return Err;
299 if (auto Err = SequenceTraits<ChannelT>::emitSeparator(C))
300 return Err;
301 return SequenceSerialization<ChannelT, ArgTs...>::
302 serialize(C, std::forward<CArgTs>(CArgs)...);
303 }
304
305 template <typename CArgT, typename... CArgTs>
306 static Error deserialize(ChannelT &C, CArgT &CArg,
307 CArgTs &... CArgs) {
308 if (auto Err =
68
Calling 'Error::operator bool'
77
Returning from 'Error::operator bool'
78
Taking true branch
309 SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg))
18
Calling 'SerializationTraits::deserialize'
42
Returning from 'SerializationTraits::deserialize'
43
Calling move constructor for 'Error'
67
Returning from move constructor for 'Error'
310 return Err;
79
Calling '~Error'
86
Returning from '~Error'
311 if (auto Err = SequenceTraits<ChannelT>::consumeSeparator(C))
312 return Err;
313 return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, CArgs...);
314 }
315};
316
317template <typename ChannelT, typename... ArgTs>
318Error serializeSeq(ChannelT &C, ArgTs &&... Args) {
319 return SequenceSerialization<ChannelT, typename std::decay<ArgTs>::type...>::
320 serialize(C, std::forward<ArgTs>(Args)...);
321}
322
323template <typename ChannelT, typename... ArgTs>
324Error deserializeSeq(ChannelT &C, ArgTs &... Args) {
325 return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, Args...);
17
Calling 'SequenceSerialization::deserialize'
87
Returning from 'SequenceSerialization::deserialize'
326}
327
328template <typename ChannelT>
329class SerializationTraits<ChannelT, Error> {
330public:
331
332 using WrappedErrorSerializer =
333 std::function<Error(ChannelT &C, const ErrorInfoBase&)>;
334
335 using WrappedErrorDeserializer =
336 std::function<Error(ChannelT &C, Error &Err)>;
337
338 template <typename ErrorInfoT, typename SerializeFtor,
339 typename DeserializeFtor>
340 static void registerErrorType(std::string Name, SerializeFtor Serialize,
341 DeserializeFtor Deserialize) {
342 assert(!Name.empty() &&(static_cast <bool> (!Name.empty() && "The empty string is reserved for the Success value"
) ? void (0) : __assert_fail ("!Name.empty() && \"The empty string is reserved for the Success value\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCSerialization.h"
, 343, __extension__ __PRETTY_FUNCTION__))
343 "The empty string is reserved for the Success value")(static_cast <bool> (!Name.empty() && "The empty string is reserved for the Success value"
) ? void (0) : __assert_fail ("!Name.empty() && \"The empty string is reserved for the Success value\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCSerialization.h"
, 343, __extension__ __PRETTY_FUNCTION__))
;
344
345 const std::string *KeyName = nullptr;
346 {
347 // We're abusing the stability of std::map here: We take a reference to the
348 // key of the deserializers map to save us from duplicating the string in
349 // the serializer. This should be changed to use a stringpool if we switch
350 // to a map type that may move keys in memory.
351 std::lock_guard<std::recursive_mutex> Lock(DeserializersMutex);
352 auto I =
353 Deserializers.insert(Deserializers.begin(),
354 std::make_pair(std::move(Name),
355 std::move(Deserialize)));
356 KeyName = &I->first;
357 }
358
359 {
360 assert(KeyName != nullptr && "No keyname pointer")(static_cast <bool> (KeyName != nullptr && "No keyname pointer"
) ? void (0) : __assert_fail ("KeyName != nullptr && \"No keyname pointer\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCSerialization.h"
, 360, __extension__ __PRETTY_FUNCTION__))
;
361 std::lock_guard<std::recursive_mutex> Lock(SerializersMutex);
362 // FIXME: Move capture Serialize once we have C++14.
363 Serializers[ErrorInfoT::classID()] =
364 [KeyName, Serialize](ChannelT &C, const ErrorInfoBase &EIB) -> Error {
365 assert(EIB.dynamicClassID() == ErrorInfoT::classID() &&(static_cast <bool> (EIB.dynamicClassID() == ErrorInfoT
::classID() && "Serializer called for wrong error type"
) ? void (0) : __assert_fail ("EIB.dynamicClassID() == ErrorInfoT::classID() && \"Serializer called for wrong error type\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCSerialization.h"
, 366, __extension__ __PRETTY_FUNCTION__))
366 "Serializer called for wrong error type")(static_cast <bool> (EIB.dynamicClassID() == ErrorInfoT
::classID() && "Serializer called for wrong error type"
) ? void (0) : __assert_fail ("EIB.dynamicClassID() == ErrorInfoT::classID() && \"Serializer called for wrong error type\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCSerialization.h"
, 366, __extension__ __PRETTY_FUNCTION__))
;
367 if (auto Err = serializeSeq(C, *KeyName))
368 return Err;
369 return Serialize(C, static_cast<const ErrorInfoT &>(EIB));
370 };
371 }
372 }
373
374 static Error serialize(ChannelT &C, Error &&Err) {
375 std::lock_guard<std::recursive_mutex> Lock(SerializersMutex);
376
377 if (!Err)
378 return serializeSeq(C, std::string());
379
380 return handleErrors(std::move(Err),
381 [&C](const ErrorInfoBase &EIB) {
382 auto SI = Serializers.find(EIB.dynamicClassID());
383 if (SI == Serializers.end())
384 return serializeAsStringError(C, EIB);
385 return (SI->second)(C, EIB);
386 });
387 }
388
389 static Error deserialize(ChannelT &C, Error &Err) {
390 std::lock_guard<std::recursive_mutex> Lock(DeserializersMutex);
391
392 std::string Key;
393 if (auto Err = deserializeSeq(C, Key))
394 return Err;
395
396 if (Key.empty()) {
397 ErrorAsOutParameter EAO(&Err);
398 Err = Error::success();
399 return Error::success();
400 }
401
402 auto DI = Deserializers.find(Key);
403 assert(DI != Deserializers.end() && "No deserializer for error type")(static_cast <bool> (DI != Deserializers.end() &&
"No deserializer for error type") ? void (0) : __assert_fail
("DI != Deserializers.end() && \"No deserializer for error type\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCSerialization.h"
, 403, __extension__ __PRETTY_FUNCTION__))
;
404 return (DI->second)(C, Err);
405 }
406
407private:
408
409 static Error serializeAsStringError(ChannelT &C, const ErrorInfoBase &EIB) {
410 std::string ErrMsg;
411 {
412 raw_string_ostream ErrMsgStream(ErrMsg);
413 EIB.log(ErrMsgStream);
414 }
415 return serialize(C, make_error<StringError>(std::move(ErrMsg),
416 inconvertibleErrorCode()));
417 }
418
419 static std::recursive_mutex SerializersMutex;
420 static std::recursive_mutex DeserializersMutex;
421 static std::map<const void*, WrappedErrorSerializer> Serializers;
422 static std::map<std::string, WrappedErrorDeserializer> Deserializers;
423};
424
425template <typename ChannelT>
426std::recursive_mutex SerializationTraits<ChannelT, Error>::SerializersMutex;
427
428template <typename ChannelT>
429std::recursive_mutex SerializationTraits<ChannelT, Error>::DeserializersMutex;
430
431template <typename ChannelT>
432std::map<const void*,
433 typename SerializationTraits<ChannelT, Error>::WrappedErrorSerializer>
434SerializationTraits<ChannelT, Error>::Serializers;
435
436template <typename ChannelT>
437std::map<std::string,
438 typename SerializationTraits<ChannelT, Error>::WrappedErrorDeserializer>
439SerializationTraits<ChannelT, Error>::Deserializers;
440
441/// Registers a serializer and deserializer for the given error type on the
442/// given channel type.
443template <typename ChannelT, typename ErrorInfoT, typename SerializeFtor,
444 typename DeserializeFtor>
445void registerErrorSerialization(std::string Name, SerializeFtor &&Serialize,
446 DeserializeFtor &&Deserialize) {
447 SerializationTraits<ChannelT, Error>::template registerErrorType<ErrorInfoT>(
448 std::move(Name),
449 std::forward<SerializeFtor>(Serialize),
450 std::forward<DeserializeFtor>(Deserialize));
451}
452
453/// Registers serialization/deserialization for StringError.
454template <typename ChannelT>
455void registerStringError() {
456 static bool AlreadyRegistered = false;
457 if (!AlreadyRegistered) {
458 registerErrorSerialization<ChannelT, StringError>(
459 "StringError",
460 [](ChannelT &C, const StringError &SE) {
461 return serializeSeq(C, SE.getMessage());
462 },
463 [](ChannelT &C, Error &Err) -> Error {
464 ErrorAsOutParameter EAO(&Err);
465 std::string Msg;
466 if (auto E2 = deserializeSeq(C, Msg))
467 return E2;
468 Err =
469 make_error<StringError>(std::move(Msg),
470 orcError(
471 OrcErrorCode::UnknownErrorCodeFromRemote));
472 return Error::success();
473 });
474 AlreadyRegistered = true;
475 }
476}
477
478/// SerializationTraits for Expected<T1> from an Expected<T2>.
479template <typename ChannelT, typename T1, typename T2>
480class SerializationTraits<ChannelT, Expected<T1>, Expected<T2>> {
481public:
482
483 static Error serialize(ChannelT &C, Expected<T2> &&ValOrErr) {
484 if (ValOrErr) {
485 if (auto Err = serializeSeq(C, true))
486 return Err;
487 return SerializationTraits<ChannelT, T1, T2>::serialize(C, *ValOrErr);
488 }
489 if (auto Err = serializeSeq(C, false))
490 return Err;
491 return serializeSeq(C, ValOrErr.takeError());
492 }
493
494 static Error deserialize(ChannelT &C, Expected<T2> &ValOrErr) {
495 ExpectedAsOutParameter<T2> EAO(&ValOrErr);
496 bool HasValue;
497 if (auto Err = deserializeSeq(C, HasValue))
498 return Err;
499 if (HasValue)
500 return SerializationTraits<ChannelT, T1, T2>::deserialize(C, *ValOrErr);
501 Error Err = Error::success();
502 if (auto E2 = deserializeSeq(C, Err))
503 return E2;
504 ValOrErr = std::move(Err);
505 return Error::success();
506 }
507};
508
509/// SerializationTraits for Expected<T1> from a T2.
510template <typename ChannelT, typename T1, typename T2>
511class SerializationTraits<ChannelT, Expected<T1>, T2> {
512public:
513
514 static Error serialize(ChannelT &C, T2 &&Val) {
515 return serializeSeq(C, Expected<T2>(std::forward<T2>(Val)));
516 }
517};
518
519/// SerializationTraits for Expected<T1> from an Error.
520template <typename ChannelT, typename T>
521class SerializationTraits<ChannelT, Expected<T>, Error> {
522public:
523
524 static Error serialize(ChannelT &C, Error &&Err) {
525 return serializeSeq(C, Expected<T>(std::move(Err)));
526 }
527};
528
529/// SerializationTraits default specialization for std::pair.
530template <typename ChannelT, typename T1, typename T2>
531class SerializationTraits<ChannelT, std::pair<T1, T2>> {
532public:
533 static Error serialize(ChannelT &C, const std::pair<T1, T2> &V) {
534 return serializeSeq(C, V.first, V.second);
535 }
536
537 static Error deserialize(ChannelT &C, std::pair<T1, T2> &V) {
538 return deserializeSeq(C, V.first, V.second);
539 }
540};
541
542/// SerializationTraits default specialization for std::tuple.
543template <typename ChannelT, typename... ArgTs>
544class SerializationTraits<ChannelT, std::tuple<ArgTs...>> {
545public:
546
547 /// RPC channel serialization for std::tuple.
548 static Error serialize(ChannelT &C, const std::tuple<ArgTs...> &V) {
549 return serializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
550 }
551
552 /// RPC channel deserialization for std::tuple.
553 static Error deserialize(ChannelT &C, std::tuple<ArgTs...> &V) {
554 return deserializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>());
555 }
556
557private:
558 // Serialization helper for std::tuple.
559 template <size_t... Is>
560 static Error serializeTupleHelper(ChannelT &C, const std::tuple<ArgTs...> &V,
561 llvm::index_sequence<Is...> _) {
562 return serializeSeq(C, std::get<Is>(V)...);
563 }
564
565 // Serialization helper for std::tuple.
566 template <size_t... Is>
567 static Error deserializeTupleHelper(ChannelT &C, std::tuple<ArgTs...> &V,
568 llvm::index_sequence<Is...> _) {
569 return deserializeSeq(C, std::get<Is>(V)...);
570 }
571};
572
573/// SerializationTraits default specialization for std::vector.
574template <typename ChannelT, typename T>
575class SerializationTraits<ChannelT, std::vector<T>> {
576public:
577
578 /// Serialize a std::vector<T> from std::vector<T>.
579 static Error serialize(ChannelT &C, const std::vector<T> &V) {
580 if (auto Err = serializeSeq(C, static_cast<uint64_t>(V.size())))
581 return Err;
582
583 for (const auto &E : V)
584 if (auto Err = serializeSeq(C, E))
585 return Err;
586
587 return Error::success();
588 }
589
590 /// Deserialize a std::vector<T> to a std::vector<T>.
591 static Error deserialize(ChannelT &C, std::vector<T> &V) {
592 uint64_t Count = 0;
593 if (auto Err = deserializeSeq(C, Count))
594 return Err;
595
596 V.resize(Count);
597 for (auto &E : V)
598 if (auto Err = deserializeSeq(C, E))
599 return Err;
600
601 return Error::success();
602 }
603};
604
605} // end namespace rpc
606} // end namespace orc
607} // end namespace llvm
608
609#endif // LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H

/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h

1//===- llvm/Support/Error.h - Recoverable error handling --------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines an API used to report recoverable errors.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_SUPPORT_ERROR_H
15#define LLVM_SUPPORT_ERROR_H
16
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/ADT/Twine.h"
21#include "llvm/Config/abi-breaking.h"
22#include "llvm/Support/AlignOf.h"
23#include "llvm/Support/Compiler.h"
24#include "llvm/Support/Debug.h"
25#include "llvm/Support/ErrorHandling.h"
26#include "llvm/Support/ErrorOr.h"
27#include "llvm/Support/raw_ostream.h"
28#include <algorithm>
29#include <cassert>
30#include <cstdint>
31#include <cstdlib>
32#include <functional>
33#include <memory>
34#include <new>
35#include <string>
36#include <system_error>
37#include <type_traits>
38#include <utility>
39#include <vector>
40
41namespace llvm {
42
43class ErrorSuccess;
44
45/// Base class for error info classes. Do not extend this directly: Extend
46/// the ErrorInfo template subclass instead.
47class ErrorInfoBase {
48public:
49 virtual ~ErrorInfoBase() = default;
50
51 /// Print an error message to an output stream.
52 virtual void log(raw_ostream &OS) const = 0;
53
54 /// Return the error message as a string.
55 virtual std::string message() const {
56 std::string Msg;
57 raw_string_ostream OS(Msg);
58 log(OS);
59 return OS.str();
60 }
61
62 /// Convert this error to a std::error_code.
63 ///
64 /// This is a temporary crutch to enable interaction with code still
65 /// using std::error_code. It will be removed in the future.
66 virtual std::error_code convertToErrorCode() const = 0;
67
68 // Returns the class ID for this type.
69 static const void *classID() { return &ID; }
70
71 // Returns the class ID for the dynamic type of this ErrorInfoBase instance.
72 virtual const void *dynamicClassID() const = 0;
73
74 // Check whether this instance is a subclass of the class identified by
75 // ClassID.
76 virtual bool isA(const void *const ClassID) const {
77 return ClassID == classID();
78 }
79
80 // Check whether this instance is a subclass of ErrorInfoT.
81 template <typename ErrorInfoT> bool isA() const {
82 return isA(ErrorInfoT::classID());
83 }
84
85private:
86 virtual void anchor();
87
88 static char ID;
89};
90
91/// Lightweight error class with error context and mandatory checking.
92///
93/// Instances of this class wrap a ErrorInfoBase pointer. Failure states
94/// are represented by setting the pointer to a ErrorInfoBase subclass
95/// instance containing information describing the failure. Success is
96/// represented by a null pointer value.
97///
98/// Instances of Error also contains a 'Checked' flag, which must be set
99/// before the destructor is called, otherwise the destructor will trigger a
100/// runtime error. This enforces at runtime the requirement that all Error
101/// instances be checked or returned to the caller.
102///
103/// There are two ways to set the checked flag, depending on what state the
104/// Error instance is in. For Error instances indicating success, it
105/// is sufficient to invoke the boolean conversion operator. E.g.:
106///
107/// @code{.cpp}
108/// Error foo(<...>);
109///
110/// if (auto E = foo(<...>))
111/// return E; // <- Return E if it is in the error state.
112/// // We have verified that E was in the success state. It can now be safely
113/// // destroyed.
114/// @endcode
115///
116/// A success value *can not* be dropped. For example, just calling 'foo(<...>)'
117/// without testing the return value will raise a runtime error, even if foo
118/// returns success.
119///
120/// For Error instances representing failure, you must use either the
121/// handleErrors or handleAllErrors function with a typed handler. E.g.:
122///
123/// @code{.cpp}
124/// class MyErrorInfo : public ErrorInfo<MyErrorInfo> {
125/// // Custom error info.
126/// };
127///
128/// Error foo(<...>) { return make_error<MyErrorInfo>(...); }
129///
130/// auto E = foo(<...>); // <- foo returns failure with MyErrorInfo.
131/// auto NewE =
132/// handleErrors(E,
133/// [](const MyErrorInfo &M) {
134/// // Deal with the error.
135/// },
136/// [](std::unique_ptr<OtherError> M) -> Error {
137/// if (canHandle(*M)) {
138/// // handle error.
139/// return Error::success();
140/// }
141/// // Couldn't handle this error instance. Pass it up the stack.
142/// return Error(std::move(M));
143/// );
144/// // Note - we must check or return NewE in case any of the handlers
145/// // returned a new error.
146/// @endcode
147///
148/// The handleAllErrors function is identical to handleErrors, except
149/// that it has a void return type, and requires all errors to be handled and
150/// no new errors be returned. It prevents errors (assuming they can all be
151/// handled) from having to be bubbled all the way to the top-level.
152///
153/// *All* Error instances must be checked before destruction, even if
154/// they're moved-assigned or constructed from Success values that have already
155/// been checked. This enforces checking through all levels of the call stack.
156class LLVM_NODISCARD[[clang::warn_unused_result]] Error {
157 // ErrorList needs to be able to yank ErrorInfoBase pointers out of this
158 // class to add to the error list.
159 friend class ErrorList;
160
161 // handleErrors needs to be able to set the Checked flag.
162 template <typename... HandlerTs>
163 friend Error handleErrors(Error E, HandlerTs &&... Handlers);
164
165 // Expected<T> needs to be able to steal the payload when constructed from an
166 // error.
167 template <typename T> friend class Expected;
168
169protected:
170 /// Create a success value. Prefer using 'Error::success()' for readability
171 Error() {
172 setPtr(nullptr);
173 setChecked(false);
174 }
175
176public:
177 /// Create a success value.
178 static ErrorSuccess success();
179
180 // Errors are not copy-constructable.
181 Error(const Error &Other) = delete;
182
183 /// Move-construct an error value. The newly constructed error is considered
184 /// unchecked, even if the source error had been checked. The original error
185 /// becomes a checked Success value, regardless of its original state.
186 Error(Error &&Other) {
187 setChecked(true);
44
Calling 'Error::setChecked'
46
Returning from 'Error::setChecked'
90
Calling 'Error::setChecked'
92
Returning from 'Error::setChecked'
188 *this = std::move(Other);
20
Calling 'move'
21
Returning from 'move'
22
Calling move assignment operator for 'Error'
29
Returning from move assignment operator for 'Error'
47
Calling 'move'
48
Returning from 'move'
49
Calling move assignment operator for 'Error'
66
Returning from move assignment operator for 'Error'
93
Calling 'move'
94
Returning from 'move'
95
Calling move assignment operator for 'Error'
112
Returning from move assignment operator for 'Error'
189 }
190
191 /// Create an error value. Prefer using the 'make_error' function, but
192 /// this constructor can be useful when "re-throwing" errors from handlers.
193 Error(std::unique_ptr<ErrorInfoBase> Payload) {
194 setPtr(Payload.release());
195 setChecked(false);
196 }
197
198 // Errors are not copy-assignable.
199 Error &operator=(const Error &Other) = delete;
200
201 /// Move-assign an error value. The current error must represent success, you
202 /// you cannot overwrite an unhandled error. The current error is then
203 /// considered unchecked. The source error becomes a checked success value,
204 /// regardless of its original state.
205 Error &operator=(Error &&Other) {
206 // Don't allow overwriting of unchecked values.
207 assertIsChecked();
50
Calling 'Error::assertIsChecked'
53
Returning from 'Error::assertIsChecked'
96
Calling 'Error::assertIsChecked'
99
Returning from 'Error::assertIsChecked'
208 setPtr(Other.getPtr());
23
Calling 'Error::getPtr'
24
Returning from 'Error::getPtr'
25
Calling 'Error::setPtr'
26
Returning from 'Error::setPtr'
54
Calling 'Error::getPtr'
55
Returning from 'Error::getPtr'
56
Calling 'Error::setPtr'
57
Returning from 'Error::setPtr'
100
Calling 'Error::getPtr'
101
Returning from 'Error::getPtr'
102
Calling 'Error::setPtr'
103
Returning from 'Error::setPtr'
209
210 // This Error is unchecked, even if the source error was checked.
211 setChecked(false);
58
Calling 'Error::setChecked'
60
Returning from 'Error::setChecked'
104
Calling 'Error::setChecked'
106
Returning from 'Error::setChecked'
212
213 // Null out Other's payload and set its checked bit.
214 Other.setPtr(nullptr);
27
Calling 'Error::setPtr'
28
Returning from 'Error::setPtr'
61
Calling 'Error::setPtr'
62
Returning from 'Error::setPtr'
107
Calling 'Error::setPtr'
108
Returning from 'Error::setPtr'
215 Other.setChecked(true);
63
Calling 'Error::setChecked'
65
Returning from 'Error::setChecked'
109
Calling 'Error::setChecked'
111
Returning from 'Error::setChecked'
216
217 return *this;
218 }
219
220 /// Destroy a Error. Fails with a call to abort() if the error is
221 /// unchecked.
222 ~Error() {
223 assertIsChecked();
80
Calling 'Error::assertIsChecked'
83
Returning from 'Error::assertIsChecked'
126
Calling 'Error::assertIsChecked'
129
Returning from 'Error::assertIsChecked'
224 delete getPtr();
39
Calling 'Error::getPtr'
40
Returning from 'Error::getPtr'
84
Calling 'Error::getPtr'
85
Returning from 'Error::getPtr'
130
Calling 'Error::getPtr'
131
Returning from 'Error::getPtr'
225 }
226
227 /// Bool conversion. Returns true if this Error is in a failure state,
228 /// and false if it is in an accept state. If the error is in a Success state
229 /// it will be considered checked.
230 explicit operator bool() {
231 setChecked(getPtr() == nullptr);
32
Calling 'Error::getPtr'
33
Returning from 'Error::getPtr'
69
Calling 'Error::getPtr'
70
Returning from 'Error::getPtr'
71
Calling 'Error::setChecked'
74
Returning from 'Error::setChecked'
115
Calling 'Error::getPtr'
116
Returning from 'Error::getPtr'
117
Calling 'Error::setChecked'
120
Returning from 'Error::setChecked'
232 return getPtr() != nullptr;
34
Calling 'Error::getPtr'
35
Returning from 'Error::getPtr'
75
Calling 'Error::getPtr'
76
Returning from 'Error::getPtr'
121
Calling 'Error::getPtr'
122
Returning from 'Error::getPtr'
233 }
234
235 /// Check whether one error is a subclass of another.
236 template <typename ErrT> bool isA() const {
237 return getPtr() && getPtr()->isA(ErrT::classID());
238 }
239
240 /// Returns the dynamic class id of this error, or null if this is a success
241 /// value.
242 const void* dynamicClassID() const {
243 if (!getPtr())
244 return nullptr;
245 return getPtr()->dynamicClassID();
246 }
247
248private:
249#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
250 // assertIsChecked() happens very frequently, but under normal circumstances
251 // is supposed to be a no-op. So we want it to be inlined, but having a bunch
252 // of debug prints can cause the function to be too large for inlining. So
253 // it's important that we define this function out of line so that it can't be
254 // inlined.
255 LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn))
256 void fatalUncheckedError() const;
257#endif
258
259 void assertIsChecked() {
260#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
261 if (LLVM_UNLIKELY(!getChecked() || getPtr())__builtin_expect((bool)(!getChecked() || getPtr()), false))
51
Within the expansion of the macro 'LLVM_UNLIKELY':
a
Calling 'Error::getChecked'
b
Returning from 'Error::getChecked'
c
Calling 'Error::getPtr'
d
Returning from 'Error::getPtr'
52
Taking false branch
81
Within the expansion of the macro 'LLVM_UNLIKELY':
a
Calling 'Error::getChecked'
b
Returning from 'Error::getChecked'
82
Taking false branch
97
Within the expansion of the macro 'LLVM_UNLIKELY':
a
Calling 'Error::getChecked'
b
Returning from 'Error::getChecked'
c
Calling 'Error::getPtr'
d
Returning from 'Error::getPtr'
98
Taking false branch
127
Within the expansion of the macro 'LLVM_UNLIKELY':
a
Calling 'Error::getChecked'
b
Returning from 'Error::getChecked'
128
Taking false branch
262 fatalUncheckedError();
263#endif
264 }
265
266 ErrorInfoBase *getPtr() const {
267 return reinterpret_cast<ErrorInfoBase*>(
268 reinterpret_cast<uintptr_t>(Payload) &
269 ~static_cast<uintptr_t>(0x1));
270 }
271
272 void setPtr(ErrorInfoBase *EI) {
273#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
274 Payload = reinterpret_cast<ErrorInfoBase*>(
275 (reinterpret_cast<uintptr_t>(EI) &
276 ~static_cast<uintptr_t>(0x1)) |
277 (reinterpret_cast<uintptr_t>(Payload) & 0x1));
278#else
279 Payload = EI;
280#endif
281 }
282
283 bool getChecked() const {
284#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
285 return (reinterpret_cast<uintptr_t>(Payload) & 0x1) == 0;
286#else
287 return true;
288#endif
289 }
290
291 void setChecked(bool V) {
292 Payload = reinterpret_cast<ErrorInfoBase*>(
293 (reinterpret_cast<uintptr_t>(Payload) &
294 ~static_cast<uintptr_t>(0x1)) |
295 (V ? 0 : 1));
45
'?' condition is true
59
'?' condition is false
64
'?' condition is true
72
Assuming 'V' is 0
73
'?' condition is false
91
'?' condition is true
105
'?' condition is false
110
'?' condition is true
118
Assuming 'V' is not equal to 0
119
'?' condition is true
296 }
297
298 std::unique_ptr<ErrorInfoBase> takePayload() {
299 std::unique_ptr<ErrorInfoBase> Tmp(getPtr());
300 setPtr(nullptr);
301 setChecked(true);
302 return Tmp;
303 }
304
305 ErrorInfoBase *Payload = nullptr;
306};
307
308/// Subclass of Error for the sole purpose of identifying the success path in
309/// the type system. This allows to catch invalid conversion to Expected<T> at
310/// compile time.
311class ErrorSuccess : public Error {};
312
313inline ErrorSuccess Error::success() { return ErrorSuccess(); }
314
315/// Make a Error instance representing failure using the given error info
316/// type.
317template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) {
318 return Error(llvm::make_unique<ErrT>(std::forward<ArgTs>(Args)...));
319}
320
321/// Base class for user error types. Users should declare their error types
322/// like:
323///
324/// class MyError : public ErrorInfo<MyError> {
325/// ....
326/// };
327///
328/// This class provides an implementation of the ErrorInfoBase::kind
329/// method, which is used by the Error RTTI system.
330template <typename ThisErrT, typename ParentErrT = ErrorInfoBase>
331class ErrorInfo : public ParentErrT {
332public:
333 static const void *classID() { return &ThisErrT::ID; }
334
335 const void *dynamicClassID() const override { return &ThisErrT::ID; }
336
337 bool isA(const void *const ClassID) const override {
338 return ClassID == classID() || ParentErrT::isA(ClassID);
339 }
340};
341
342/// Special ErrorInfo subclass representing a list of ErrorInfos.
343/// Instances of this class are constructed by joinError.
344class ErrorList final : public ErrorInfo<ErrorList> {
345 // handleErrors needs to be able to iterate the payload list of an
346 // ErrorList.
347 template <typename... HandlerTs>
348 friend Error handleErrors(Error E, HandlerTs &&... Handlers);
349
350 // joinErrors is implemented in terms of join.
351 friend Error joinErrors(Error, Error);
352
353public:
354 void log(raw_ostream &OS) const override {
355 OS << "Multiple errors:\n";
356 for (auto &ErrPayload : Payloads) {
357 ErrPayload->log(OS);
358 OS << "\n";
359 }
360 }
361
362 std::error_code convertToErrorCode() const override;
363
364 // Used by ErrorInfo::classID.
365 static char ID;
366
367private:
368 ErrorList(std::unique_ptr<ErrorInfoBase> Payload1,
369 std::unique_ptr<ErrorInfoBase> Payload2) {
370 assert(!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() &&(static_cast <bool> (!Payload1->isA<ErrorList>
() && !Payload2->isA<ErrorList>() &&
"ErrorList constructor payloads should be singleton errors")
? void (0) : __assert_fail ("!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && \"ErrorList constructor payloads should be singleton errors\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h"
, 371, __extension__ __PRETTY_FUNCTION__))
371 "ErrorList constructor payloads should be singleton errors")(static_cast <bool> (!Payload1->isA<ErrorList>
() && !Payload2->isA<ErrorList>() &&
"ErrorList constructor payloads should be singleton errors")
? void (0) : __assert_fail ("!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && \"ErrorList constructor payloads should be singleton errors\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h"
, 371, __extension__ __PRETTY_FUNCTION__))
;
372 Payloads.push_back(std::move(Payload1));
373 Payloads.push_back(std::move(Payload2));
374 }
375
376 static Error join(Error E1, Error E2) {
377 if (!E1)
378 return E2;
379 if (!E2)
380 return E1;
381 if (E1.isA<ErrorList>()) {
382 auto &E1List = static_cast<ErrorList &>(*E1.getPtr());
383 if (E2.isA<ErrorList>()) {
384 auto E2Payload = E2.takePayload();
385 auto &E2List = static_cast<ErrorList &>(*E2Payload);
386 for (auto &Payload : E2List.Payloads)
387 E1List.Payloads.push_back(std::move(Payload));
388 } else
389 E1List.Payloads.push_back(E2.takePayload());
390
391 return E1;
392 }
393 if (E2.isA<ErrorList>()) {
394 auto &E2List = static_cast<ErrorList &>(*E2.getPtr());
395 E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload());
396 return E2;
397 }
398 return Error(std::unique_ptr<ErrorList>(
399 new ErrorList(E1.takePayload(), E2.takePayload())));
400 }
401
402 std::vector<std::unique_ptr<ErrorInfoBase>> Payloads;
403};
404
405/// Concatenate errors. The resulting Error is unchecked, and contains the
406/// ErrorInfo(s), if any, contained in E1, followed by the
407/// ErrorInfo(s), if any, contained in E2.
408inline Error joinErrors(Error E1, Error E2) {
409 return ErrorList::join(std::move(E1), std::move(E2));
410}
411
412/// Tagged union holding either a T or a Error.
413///
414/// This class parallels ErrorOr, but replaces error_code with Error. Since
415/// Error cannot be copied, this class replaces getError() with
416/// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the
417/// error class type.
418template <class T> class LLVM_NODISCARD[[clang::warn_unused_result]] Expected {
419 template <class T1> friend class ExpectedAsOutParameter;
420 template <class OtherT> friend class Expected;
421
422 static const bool isRef = std::is_reference<T>::value;
423
424 using wrap = ReferenceStorage<typename std::remove_reference<T>::type>;
425
426 using error_type = std::unique_ptr<ErrorInfoBase>;
427
428public:
429 using storage_type = typename std::conditional<isRef, wrap, T>::type;
430 using value_type = T;
431
432private:
433 using reference = typename std::remove_reference<T>::type &;
434 using const_reference = const typename std::remove_reference<T>::type &;
435 using pointer = typename std::remove_reference<T>::type *;
436 using const_pointer = const typename std::remove_reference<T>::type *;
437
438public:
439 /// Create an Expected<T> error value from the given Error.
440 Expected(Error Err)
441 : HasError(true)
442#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
443 // Expected is unchecked upon construction in Debug builds.
444 , Unchecked(true)
445#endif
446 {
447 assert(Err && "Cannot create Expected<T> from Error success value.")(static_cast <bool> (Err && "Cannot create Expected<T> from Error success value."
) ? void (0) : __assert_fail ("Err && \"Cannot create Expected<T> from Error success value.\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h"
, 447, __extension__ __PRETTY_FUNCTION__))
;
448 new (getErrorStorage()) error_type(Err.takePayload());
449 }
450
451 /// Forbid to convert from Error::success() implicitly, this avoids having
452 /// Expected<T> foo() { return Error::success(); } which compiles otherwise
453 /// but triggers the assertion above.
454 Expected(ErrorSuccess) = delete;
455
456 /// Create an Expected<T> success value from the given OtherT value, which
457 /// must be convertible to T.
458 template <typename OtherT>
459 Expected(OtherT &&Val,
460 typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
461 * = nullptr)
462 : HasError(false)
463#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
464 // Expected is unchecked upon construction in Debug builds.
465 , Unchecked(true)
466#endif
467 {
468 new (getStorage()) storage_type(std::forward<OtherT>(Val));
469 }
470
471 /// Move construct an Expected<T> value.
472 Expected(Expected &&Other) { moveConstruct(std::move(Other)); }
473
474 /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
475 /// must be convertible to T.
476 template <class OtherT>
477 Expected(Expected<OtherT> &&Other,
478 typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
479 * = nullptr) {
480 moveConstruct(std::move(Other));
481 }
482
483 /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
484 /// isn't convertible to T.
485 template <class OtherT>
486 explicit Expected(
487 Expected<OtherT> &&Other,
488 typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
489 nullptr) {
490 moveConstruct(std::move(Other));
491 }
492
493 /// Move-assign from another Expected<T>.
494 Expected &operator=(Expected &&Other) {
495 moveAssign(std::move(Other));
496 return *this;
497 }
498
499 /// Destroy an Expected<T>.
500 ~Expected() {
501 assertIsChecked();
502 if (!HasError)
503 getStorage()->~storage_type();
504 else
505 getErrorStorage()->~error_type();
506 }
507
508 /// \brief Return false if there is an error.
509 explicit operator bool() {
510#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
511 Unchecked = HasError;
512#endif
513 return !HasError;
514 }
515
516 /// \brief Returns a reference to the stored T value.
517 reference get() {
518 assertIsChecked();
519 return *getStorage();
520 }
521
522 /// \brief Returns a const reference to the stored T value.
523 const_reference get() const {
524 assertIsChecked();
525 return const_cast<Expected<T> *>(this)->get();
526 }
527
528 /// \brief Check that this Expected<T> is an error of type ErrT.
529 template <typename ErrT> bool errorIsA() const {
530 return HasError && (*getErrorStorage())->template isA<ErrT>();
531 }
532
533 /// \brief Take ownership of the stored error.
534 /// After calling this the Expected<T> is in an indeterminate state that can
535 /// only be safely destructed. No further calls (beside the destructor) should
536 /// be made on the Expected<T> vaule.
537 Error takeError() {
538#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
539 Unchecked = false;
540#endif
541 return HasError ? Error(std::move(*getErrorStorage())) : Error::success();
542 }
543
544 /// \brief Returns a pointer to the stored T value.
545 pointer operator->() {
546 assertIsChecked();
547 return toPointer(getStorage());
548 }
549
550 /// \brief Returns a const pointer to the stored T value.
551 const_pointer operator->() const {
552 assertIsChecked();
553 return toPointer(getStorage());
554 }
555
556 /// \brief Returns a reference to the stored T value.
557 reference operator*() {
558 assertIsChecked();
559 return *getStorage();
560 }
561
562 /// \brief Returns a const reference to the stored T value.
563 const_reference operator*() const {
564 assertIsChecked();
565 return *getStorage();
566 }
567
568private:
569 template <class T1>
570 static bool compareThisIfSameType(const T1 &a, const T1 &b) {
571 return &a == &b;
572 }
573
574 template <class T1, class T2>
575 static bool compareThisIfSameType(const T1 &a, const T2 &b) {
576 return false;
577 }
578
579 template <class OtherT> void moveConstruct(Expected<OtherT> &&Other) {
580 HasError = Other.HasError;
581#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
582 Unchecked = true;
583 Other.Unchecked = false;
584#endif
585
586 if (!HasError)
587 new (getStorage()) storage_type(std::move(*Other.getStorage()));
588 else
589 new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage()));
590 }
591
592 template <class OtherT> void moveAssign(Expected<OtherT> &&Other) {
593 assertIsChecked();
594
595 if (compareThisIfSameType(*this, Other))
596 return;
597
598 this->~Expected();
599 new (this) Expected(std::move(Other));
600 }
601
602 pointer toPointer(pointer Val) { return Val; }
603
604 const_pointer toPointer(const_pointer Val) const { return Val; }
605
606 pointer toPointer(wrap *Val) { return &Val->get(); }
607
608 const_pointer toPointer(const wrap *Val) const { return &Val->get(); }
609
610 storage_type *getStorage() {
611 assert(!HasError && "Cannot get value when an error exists!")(static_cast <bool> (!HasError && "Cannot get value when an error exists!"
) ? void (0) : __assert_fail ("!HasError && \"Cannot get value when an error exists!\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h"
, 611, __extension__ __PRETTY_FUNCTION__))
;
612 return reinterpret_cast<storage_type *>(TStorage.buffer);
613 }
614
615 const storage_type *getStorage() const {
616 assert(!HasError && "Cannot get value when an error exists!")(static_cast <bool> (!HasError && "Cannot get value when an error exists!"
) ? void (0) : __assert_fail ("!HasError && \"Cannot get value when an error exists!\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h"
, 616, __extension__ __PRETTY_FUNCTION__))
;
617 return reinterpret_cast<const storage_type *>(TStorage.buffer);
618 }
619
620 error_type *getErrorStorage() {
621 assert(HasError && "Cannot get error when a value exists!")(static_cast <bool> (HasError && "Cannot get error when a value exists!"
) ? void (0) : __assert_fail ("HasError && \"Cannot get error when a value exists!\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h"
, 621, __extension__ __PRETTY_FUNCTION__))
;
622 return reinterpret_cast<error_type *>(ErrorStorage.buffer);
623 }
624
625 const error_type *getErrorStorage() const {
626 assert(HasError && "Cannot get error when a value exists!")(static_cast <bool> (HasError && "Cannot get error when a value exists!"
) ? void (0) : __assert_fail ("HasError && \"Cannot get error when a value exists!\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h"
, 626, __extension__ __PRETTY_FUNCTION__))
;
627 return reinterpret_cast<const error_type *>(ErrorStorage.buffer);
628 }
629
630 // Used by ExpectedAsOutParameter to reset the checked flag.
631 void setUnchecked() {
632#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
633 Unchecked = true;
634#endif
635 }
636
637#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
638 LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn))
639 LLVM_ATTRIBUTE_NOINLINE__attribute__((noinline))
640 void fatalUncheckedExpected() const {
641 dbgs() << "Expected<T> must be checked before access or destruction.\n";
642 if (HasError) {
643 dbgs() << "Unchecked Expected<T> contained error:\n";
644 (*getErrorStorage())->log(dbgs());
645 } else
646 dbgs() << "Expected<T> value was in success state. (Note: Expected<T> "
647 "values in success mode must still be checked prior to being "
648 "destroyed).\n";
649 abort();
650 }
651#endif
652
653 void assertIsChecked() {
654#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
655 if (LLVM_UNLIKELY(Unchecked)__builtin_expect((bool)(Unchecked), false))
656 fatalUncheckedExpected();
657#endif
658 }
659
660 union {
661 AlignedCharArrayUnion<storage_type> TStorage;
662 AlignedCharArrayUnion<error_type> ErrorStorage;
663 };
664 bool HasError : 1;
665#if LLVM_ENABLE_ABI_BREAKING_CHECKS1
666 bool Unchecked : 1;
667#endif
668};
669
670/// Report a serious error, calling any installed error handler. See
671/// ErrorHandling.h.
672LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) void report_fatal_error(Error Err,
673 bool gen_crash_diag = true);
674
675/// Report a fatal error if Err is a failure value.
676///
677/// This function can be used to wrap calls to fallible functions ONLY when it
678/// is known that the Error will always be a success value. E.g.
679///
680/// @code{.cpp}
681/// // foo only attempts the fallible operation if DoFallibleOperation is
682/// // true. If DoFallibleOperation is false then foo always returns
683/// // Error::success().
684/// Error foo(bool DoFallibleOperation);
685///
686/// cantFail(foo(false));
687/// @endcode
688inline void cantFail(Error Err, const char *Msg = nullptr) {
689 if (Err) {
690 if (!Msg)
691 Msg = "Failure value returned from cantFail wrapped call";
692 llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h"
, 692)
;
693 }
694}
695
696/// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and
697/// returns the contained value.
698///
699/// This function can be used to wrap calls to fallible functions ONLY when it
700/// is known that the Error will always be a success value. E.g.
701///
702/// @code{.cpp}
703/// // foo only attempts the fallible operation if DoFallibleOperation is
704/// // true. If DoFallibleOperation is false then foo always returns an int.
705/// Expected<int> foo(bool DoFallibleOperation);
706///
707/// int X = cantFail(foo(false));
708/// @endcode
709template <typename T>
710T cantFail(Expected<T> ValOrErr, const char *Msg = nullptr) {
711 if (ValOrErr)
712 return std::move(*ValOrErr);
713 else {
714 if (!Msg)
715 Msg = "Failure value returned from cantFail wrapped call";
716 llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h"
, 716)
;
717 }
718}
719
720/// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and
721/// returns the contained reference.
722///
723/// This function can be used to wrap calls to fallible functions ONLY when it
724/// is known that the Error will always be a success value. E.g.
725///
726/// @code{.cpp}
727/// // foo only attempts the fallible operation if DoFallibleOperation is
728/// // true. If DoFallibleOperation is false then foo always returns a Bar&.
729/// Expected<Bar&> foo(bool DoFallibleOperation);
730///
731/// Bar &X = cantFail(foo(false));
732/// @endcode
733template <typename T>
734T& cantFail(Expected<T&> ValOrErr, const char *Msg = nullptr) {
735 if (ValOrErr)
736 return *ValOrErr;
737 else {
738 if (!Msg)
739 Msg = "Failure value returned from cantFail wrapped call";
740 llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h"
, 740)
;
741 }
742}
743
744/// Helper for testing applicability of, and applying, handlers for
745/// ErrorInfo types.
746template <typename HandlerT>
747class ErrorHandlerTraits
748 : public ErrorHandlerTraits<decltype(
749 &std::remove_reference<HandlerT>::type::operator())> {};
750
751// Specialization functions of the form 'Error (const ErrT&)'.
752template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> {
753public:
754 static bool appliesTo(const ErrorInfoBase &E) {
755 return E.template isA<ErrT>();
756 }
757
758 template <typename HandlerT>
759 static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
760 assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler"
) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h"
, 760, __extension__ __PRETTY_FUNCTION__))
;
761 return H(static_cast<ErrT &>(*E));
762 }
763};
764
765// Specialization functions of the form 'void (const ErrT&)'.
766template <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> {
767public:
768 static bool appliesTo(const ErrorInfoBase &E) {
769 return E.template isA<ErrT>();
770 }
771
772 template <typename HandlerT>
773 static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
774 assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler"
) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h"
, 774, __extension__ __PRETTY_FUNCTION__))
;
775 H(static_cast<ErrT &>(*E));
776 return Error::success();
777 }
778};
779
780/// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'.
781template <typename ErrT>
782class ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> {
783public:
784 static bool appliesTo(const ErrorInfoBase &E) {
785 return E.template isA<ErrT>();
786 }
787
788 template <typename HandlerT>
789 static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
790 assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler"
) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h"
, 790, __extension__ __PRETTY_FUNCTION__))
;
791 std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
792 return H(std::move(SubE));
793 }
794};
795
796/// Specialization for functions of the form 'void (std::unique_ptr<ErrT>)'.
797template <typename ErrT>
798class ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> {
799public:
800 static bool appliesTo(const ErrorInfoBase &E) {
801 return E.template isA<ErrT>();
802 }
803
804 template <typename HandlerT>
805 static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) {
806 assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler"
) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\""
, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h"
, 806, __extension__ __PRETTY_FUNCTION__))
;
807 std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release()));
808 H(std::move(SubE));
809 return Error::success();
810 }
811};
812
813// Specialization for member functions of the form 'RetT (const ErrT&)'.
814template <typename C, typename RetT, typename ErrT>
815class ErrorHandlerTraits<RetT (C::*)(ErrT &)>
816 : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
817
818// Specialization for member functions of the form 'RetT (const ErrT&) const'.
819template <typename C, typename RetT, typename ErrT>
820class ErrorHandlerTraits<RetT (C::*)(ErrT &) const>
821 : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
822
823// Specialization for member functions of the form 'RetT (const ErrT&)'.
824template <typename C, typename RetT, typename ErrT>
825class ErrorHandlerTraits<RetT (C::*)(const ErrT &)>
826 : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
827
828// Specialization for member functions of the form 'RetT (const ErrT&) const'.
829template <typename C, typename RetT, typename ErrT>
830class ErrorHandlerTraits<RetT (C::*)(const ErrT &) const>
831 : public ErrorHandlerTraits<RetT (&)(ErrT &)> {};
832
833/// Specialization for member functions of the form
834/// 'RetT (std::unique_ptr<ErrT>)'.
835template <typename C, typename RetT, typename ErrT>
836class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>)>
837 : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {};
838
839/// Specialization for member functions of the form
840/// 'RetT (std::unique_ptr<ErrT>) const'.
841template <typename C, typename RetT, typename ErrT>
842class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const>
843 : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {};
844
845inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) {
846 return Error(std::move(Payload));
847}
848
849template <typename HandlerT, typename... HandlerTs>
850Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload,
851 HandlerT &&Handler, HandlerTs &&... Handlers) {
852 if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload))
853 return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler),
854 std::move(Payload));
855 return handleErrorImpl(std::move(Payload),
856 std::forward<HandlerTs>(Handlers)...);
857}
858
859/// Pass the ErrorInfo(s) contained in E to their respective handlers. Any
860/// unhandled errors (or Errors returned by handlers) are re-concatenated and
861/// returned.
862/// Because this function returns an error, its result must also be checked
863/// or returned. If you intend to handle all errors use handleAllErrors
864/// (which returns void, and will abort() on unhandled errors) instead.
865template <typename... HandlerTs>
866Error handleErrors(Error E, HandlerTs &&... Hs) {
867 if (!E)
868 return Error::success();
869
870 std::unique_ptr<ErrorInfoBase> Payload = E.takePayload();
871
872 if (Payload->isA<ErrorList>()) {
873 ErrorList &List = static_cast<ErrorList &>(*Payload);
874 Error R;
875 for (auto &P : List.Payloads)
876 R = ErrorList::join(
877 std::move(R),
878 handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...));
879 return R;
880 }
881
882 return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...);
883}
884
885/// Behaves the same as handleErrors, except that it requires that all
886/// errors be handled by the given handlers. If any unhandled error remains
887/// after the handlers have run, report_fatal_error() will be called.
888template <typename... HandlerTs>
889void handleAllErrors(Error E, HandlerTs &&... Handlers) {
890 cantFail(handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...));
891}
892
893/// Check that E is a non-error, then drop it.
894/// If E is an error report_fatal_error will be called.
895inline void handleAllErrors(Error E) {
896 cantFail(std::move(E));
897}
898
899/// Handle any errors (if present) in an Expected<T>, then try a recovery path.
900///
901/// If the incoming value is a success value it is returned unmodified. If it
902/// is a failure value then it the contained error is passed to handleErrors.
903/// If handleErrors is able to handle the error then the RecoveryPath functor
904/// is called to supply the final result. If handleErrors is not able to
905/// handle all errors then the unhandled errors are returned.
906///
907/// This utility enables the follow pattern:
908///
909/// @code{.cpp}
910/// enum FooStrategy { Aggressive, Conservative };
911/// Expected<Foo> foo(FooStrategy S);
912///
913/// auto ResultOrErr =
914/// handleExpected(
915/// foo(Aggressive),
916/// []() { return foo(Conservative); },
917/// [](AggressiveStrategyError&) {
918/// // Implicitly conusme this - we'll recover by using a conservative
919/// // strategy.
920/// });
921///
922/// @endcode
923template <typename T, typename RecoveryFtor, typename... HandlerTs>
924Expected<T> handleExpected(Expected<T> ValOrErr, RecoveryFtor &&RecoveryPath,
925 HandlerTs &&... Handlers) {
926 if (ValOrErr)
927 return ValOrErr;
928
929 if (auto Err = handleErrors(ValOrErr.takeError(),
930 std::forward<HandlerTs>(Handlers)...))
931 return std::move(Err);
932
933 return RecoveryPath();
934}
935
936/// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner
937/// will be printed before the first one is logged. A newline will be printed
938/// after each error.
939///
940/// This is useful in the base level of your program to allow clean termination
941/// (allowing clean deallocation of resources, etc.), while reporting error
942/// information to the user.
943void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner);
944
945/// Write all error messages (if any) in E to a string. The newline character
946/// is used to separate error messages.
947inline std::string toString(Error E) {
948 SmallVector<std::string, 2> Errors;
949 handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) {
950 Errors.push_back(EI.message());
951 });
952 return join(Errors.begin(), Errors.end(), "\n");
953}
954
955/// Consume a Error without doing anything. This method should be used
956/// only where an error can be considered a reasonable and expected return
957/// value.
958///
959/// Uses of this method are potentially indicative of design problems: If it's
960/// legitimate to do nothing while processing an "error", the error-producer
961/// might be more clearly refactored to return an Optional<T>.
962inline void consumeError(Error Err) {
963 handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {});
964}
965
966/// Helper for converting an Error to a bool.
967///
968/// This method returns true if Err is in an error state, or false if it is
969/// in a success state. Puts Err in a checked state in both cases (unlike
970/// Error::operator bool(), which only does this for success states).
971inline bool errorToBool(Error Err) {
972 bool IsError = static_cast<bool>(Err);
973 if (IsError)
974 consumeError(std::move(Err));
975 return IsError;
976}
977
978/// Helper for Errors used as out-parameters.
979///
980/// This helper is for use with the Error-as-out-parameter idiom, where an error
981/// is passed to a function or method by reference, rather than being returned.
982/// In such cases it is helpful to set the checked bit on entry to the function
983/// so that the error can be written to (unchecked Errors abort on assignment)
984/// and clear the checked bit on exit so that clients cannot accidentally forget
985/// to check the result. This helper performs these actions automatically using
986/// RAII:
987///
988/// @code{.cpp}
989/// Result foo(Error &Err) {
990/// ErrorAsOutParameter ErrAsOutParam(&Err); // 'Checked' flag set
991/// // <body of foo>
992/// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed.
993/// }
994/// @endcode
995///
996/// ErrorAsOutParameter takes an Error* rather than Error& so that it can be
997/// used with optional Errors (Error pointers that are allowed to be null). If
998/// ErrorAsOutParameter took an Error reference, an instance would have to be
999/// created inside every condition that verified that Error was non-null. By
1000/// taking an Error pointer we can just create one instance at the top of the
1001/// function.
1002class ErrorAsOutParameter {
1003public:
1004 ErrorAsOutParameter(Error *Err) : Err(Err) {
1005 // Raise the checked bit if Err is success.
1006 if (Err)
1007 (void)!!*Err;
1008 }
1009
1010 ~ErrorAsOutParameter() {
1011 // Clear the checked bit.
1012 if (Err && !*Err)
1013 *Err = Error::success();
1014 }
1015
1016private:
1017 Error *Err;
1018};
1019
1020/// Helper for Expected<T>s used as out-parameters.
1021///
1022/// See ErrorAsOutParameter.
1023template <typename T>
1024class ExpectedAsOutParameter {
1025public:
1026 ExpectedAsOutParameter(Expected<T> *ValOrErr)
1027 : ValOrErr(ValOrErr) {
1028 if (ValOrErr)
1029 (void)!!*ValOrErr;
1030 }
1031
1032 ~ExpectedAsOutParameter() {
1033 if (ValOrErr)
1034 ValOrErr->setUnchecked();
1035 }
1036
1037private:
1038 Expected<T> *ValOrErr;
1039};
1040
1041/// This class wraps a std::error_code in a Error.
1042///
1043/// This is useful if you're writing an interface that returns a Error
1044/// (or Expected) and you want to call code that still returns
1045/// std::error_codes.
1046class ECError : public ErrorInfo<ECError> {
1047 friend Error errorCodeToError(std::error_code);
1048
1049public:
1050 void setErrorCode(std::error_code EC) { this->EC = EC; }
1051 std::error_code convertToErrorCode() const override { return EC; }
1052 void log(raw_ostream &OS) const override { OS << EC.message(); }
1053
1054 // Used by ErrorInfo::classID.
1055 static char ID;
1056
1057protected:
1058 ECError() = default;
1059 ECError(std::error_code EC) : EC(EC) {}
1060
1061 std::error_code EC;
1062};
1063
1064/// The value returned by this function can be returned from convertToErrorCode
1065/// for Error values where no sensible translation to std::error_code exists.
1066/// It should only be used in this situation, and should never be used where a
1067/// sensible conversion to std::error_code is available, as attempts to convert
1068/// to/from this error will result in a fatal error. (i.e. it is a programmatic
1069///error to try to convert such a value).
1070std::error_code inconvertibleErrorCode();
1071
1072/// Helper for converting an std::error_code to a Error.
1073Error errorCodeToError(std::error_code EC);
1074
1075/// Helper for converting an ECError to a std::error_code.
1076///
1077/// This method requires that Err be Error() or an ECError, otherwise it
1078/// will trigger a call to abort().
1079std::error_code errorToErrorCode(Error Err);
1080
1081/// Convert an ErrorOr<T> to an Expected<T>.
1082template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) {
1083 if (auto EC = EO.getError())
1084 return errorCodeToError(EC);
1085 return std::move(*EO);
1086}
1087
1088/// Convert an Expected<T> to an ErrorOr<T>.
1089template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) {
1090 if (auto Err = E.takeError())
1091 return errorToErrorCode(std::move(Err));
1092 return std::move(*E);
1093}
1094
1095/// This class wraps a string in an Error.
1096///
1097/// StringError is useful in cases where the client is not expected to be able
1098/// to consume the specific error message programmatically (for example, if the
1099/// error message is to be presented to the user).
1100class StringError : public ErrorInfo<StringError> {
1101public:
1102 static char ID;
1103
1104 StringError(const Twine &S, std::error_code EC);
1105
1106 void log(raw_ostream &OS) const override;
1107 std::error_code convertToErrorCode() const override;
1108
1109 const std::string &getMessage() const { return Msg; }
1110
1111private:
1112 std::string Msg;
1113 std::error_code EC;
1114};
1115
1116/// Helper for check-and-exit error handling.
1117///
1118/// For tool use only. NOT FOR USE IN LIBRARY CODE.
1119///
1120class ExitOnError {
1121public:
1122 /// Create an error on exit helper.
1123 ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1)
1124 : Banner(std::move(Banner)),
1125 GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {}
1126
1127 /// Set the banner string for any errors caught by operator().
1128 void setBanner(std::string Banner) { this->Banner = std::move(Banner); }
1129
1130 /// Set the exit-code mapper function.
1131 void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) {
1132 this->GetExitCode = std::move(GetExitCode);
1133 }
1134
1135 /// Check Err. If it's in a failure state log the error(s) and exit.
1136 void operator()(Error Err) const { checkError(std::move(Err)); }
1137
1138 /// Check E. If it's in a success state then return the contained value. If
1139 /// it's in a failure state log the error(s) and exit.
1140 template <typename T> T operator()(Expected<T> &&E) const {
1141 checkError(E.takeError());
1142 return std::move(*E);
1143 }
1144
1145 /// Check E. If it's in a success state then return the contained reference. If
1146 /// it's in a failure state log the error(s) and exit.
1147 template <typename T> T& operator()(Expected<T&> &&E) const {
1148 checkError(E.takeError());
1149 return *E;
1150 }
1151
1152private:
1153 void checkError(Error Err) const {
1154 if (Err) {
1155 int ExitCode = GetExitCode(Err);
1156 logAllUnhandledErrors(std::move(Err), errs(), Banner);
1157 exit(ExitCode);
1158 }
1159 }
1160
1161 std::string Banner;
1162 std::function<int(const Error &)> GetExitCode;
1163};
1164
1165} // end namespace llvm
1166
1167#endif // LLVM_SUPPORT_ERROR_H