LLVM: include/llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13#ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_WRAPPERFUNCTIONUTILS_H
14#define LLVM_EXECUTIONENGINE_ORC_SHARED_WRAPPERFUNCTIONUTILS_H
15
19
20#include <type_traits>
21
22namespace llvm {
23namespace orc {
25
26
31
32
37
38
39
41public:
42
44
45
46
47
48
49
54
57
62
68
70 if ((R.Size > sizeof(R.Data.Value)) ||
71 (R.Size == 0 && R.Data.ValuePtr != nullptr))
72 free(R.Data.ValuePtr);
73 }
74
75
76
77
78
81 init(Tmp);
83 return Tmp;
84 }
85
86
88 assert((R.Size != 0 || R.Data.ValuePtr == nullptr) &&
89 "Cannot get data for out-of-band error value");
90 return R.Size > sizeof(R.Data.Value) ? R.Data.ValuePtr : R.Data.Value;
91 }
92
93
95 assert((R.Size != 0 || R.Data.ValuePtr == nullptr) &&
96 "Cannot get data for out-of-band error value");
97 return R.Size > sizeof(R.Data.Value) ? R.Data.ValuePtr : R.Data.Value;
98 }
99
100
102 assert((R.Size != 0 || R.Data.ValuePtr == nullptr) &&
103 "Cannot get data for out-of-band error value");
104 return R.Size;
105 }
106
107
108
109 bool empty() const { return R.Size == 0 && R.Data.ValuePtr == nullptr; }
110
111
112
114
119 return WFR;
120 }
121
122
125 memcpy(WFR.data(), Source, Size);
126 return WFR;
127 }
128
129
131 return copyFrom(Source, strlen(Source) + 1);
132 }
133
134
136 return copyFrom(Source.c_str());
137 }
138
139
141
143 char *Tmp = (char *)malloc(strlen(Msg) + 1);
144 strcpy(Tmp, Msg);
146 return WFR;
147 }
148
149
153
154
155
157 return R.Size == 0 ? R.Data.ValuePtr : nullptr;
158 }
159
160private:
162 R.Data.ValuePtr = nullptr;
163 R.Size = 0;
164 }
165
166 CWrapperFunctionResult R;
167};
168
170
171template <typename SPSArgListT, typename... ArgTs>
172WrapperFunctionResult
176 if (!SPSArgListT::serialize(OB, Args...))
178 "Error serializing arguments to blob in call");
180}
181
183public:
184 template <typename HandlerT, typename ArgTupleT, std::size_t... I>
185 static decltype(auto) call(HandlerT &&H, ArgTupleT &Args,
186 std::index_sequence<I...>) {
187 return std::forward(H)(std::get(Args)...);
188 }
189};
190
192public:
193 template <typename HandlerT, typename ArgTupleT, std::size_t... I>
195 std::index_sequence<I...>) {
196 std::forward(H)(std::get(Args)...);
198 }
199};
200
201template <typename WrapperFunctionImplT,
202 template <typename> class ResultSerializer, typename... SPSTagTs>
205 decltype(&std::remove_reference_t::operator()),
206 ResultSerializer, SPSTagTs...> {};
207
208template <typename RetT, typename... ArgTs,
209 template <typename> class ResultSerializer, typename... SPSTagTs>
211 SPSTagTs...> {
212public:
213 using ArgTuple = std::tuple<std::decay_t...>;
214 using ArgIndices = std::make_index_sequence<std::tuple_size::value>;
215
216 template
218 size_t ArgSize) {
220 if (!deserialize(ArgData, ArgSize, Args, ArgIndices{}))
222 "Could not deserialize arguments for wrapper function call");
223
225 std::forward(H), Args, ArgIndices{});
226
228 std::move(HandlerResult));
229 }
230
231private:
232 template <std::size_t... I>
233 static bool deserialize(const char *ArgData, size_t ArgSize, ArgTuple &Args,
234 std::index_sequence<I...>) {
237 }
238};
239
240
241template <typename RetT, typename... ArgTs,
242 template <typename> class ResultSerializer, typename... SPSTagTs>
244 SPSTagTs...>
246 SPSTagTs...> {};
247
248
249template <typename ClassT, typename RetT, typename... ArgTs,
250 template <typename> class ResultSerializer, typename... SPSTagTs>
252 SPSTagTs...>
254 SPSTagTs...> {};
255
256
257template <typename ClassT, typename RetT, typename... ArgTs,
258 template <typename> class ResultSerializer, typename... SPSTagTs>
263
264template <typename WrapperFunctionImplT,
265 template <typename> class ResultSerializer, typename... SPSTagTs>
268 decltype(&std::remove_reference_t::operator()),
269 ResultSerializer, SPSTagTs...> {};
270
271template <typename RetT, typename SendResultT, typename... ArgTs,
272 template <typename> class ResultSerializer, typename... SPSTagTs>
275public:
276 using ArgTuple = std::tuple<std::decay_t...>;
277 using ArgIndices = std::make_index_sequence<std::tuple_size::value>;
278
279 template <typename HandlerT, typename SendWrapperFunctionResultT>
281 SendWrapperFunctionResultT &&SendWrapperFunctionResult,
282 const char *ArgData, size_t ArgSize) {
284 if (!deserialize(ArgData, ArgSize, Args, ArgIndices{})) {
286 "Could not deserialize arguments for wrapper function call"));
287 return;
288 }
289
290 auto SendResult =
291 [SendWFR = std::move(SendWrapperFunctionResult)](auto Result) mutable {
292 using ResultT = decltype(Result);
294 };
295
296 callAsync(std::forward(H), std::move(SendResult), std::move(Args),
298 }
299
300private:
301 template <std::size_t... I>
302 static bool deserialize(const char *ArgData, size_t ArgSize, ArgTuple &Args,
303 std::index_sequence<I...>) {
306 }
307
308 template <typename HandlerT, typename SerializeAndSendResultT,
309 typename ArgTupleT, std::size_t... I>
310 static void callAsync(HandlerT &&H,
311 SerializeAndSendResultT &&SerializeAndSendResult,
312 ArgTupleT Args, std::index_sequence<I...>) {
313 (void)Args;
314 return std::forward(H)(std::move(SerializeAndSendResult),
315 std::move(std::get(Args))...);
316 }
317};
318
319
320template <typename RetT, typename... ArgTs,
321 template <typename> class ResultSerializer, typename... SPSTagTs>
323 SPSTagTs...>
325 SPSTagTs...> {};
326
327
328template <typename ClassT, typename RetT, typename... ArgTs,
329 template <typename> class ResultSerializer, typename... SPSTagTs>
334
335
336template <typename ClassT, typename RetT, typename... ArgTs,
337 template <typename> class ResultSerializer, typename... SPSTagTs>
342
350
358
359template
367
368template <typename SPSRetTagT, typename T>
376
378public:
381
386 "Error deserializing return value from blob in call",
389 }
390};
391
393public:
396
402 "Error deserializing return value from blob in call",
406 }
407};
408
409template <typename SPSTagT, typename T>
411public:
414
416 size_t ArgSize) {
421 "Error deserializing return value from blob in call",
425 }
426};
427
431
432}
433
435
436template <typename SPSRetTagT, typename... SPSTagTs>
438private:
439 template
441
442public:
443
444
445 template <typename CallerFn, typename RetT, typename... ArgTs>
447 const ArgTs &...Args) {
448
449
450
451
453
454 auto ArgBuffer =
456 Args...);
457 if (const char *ErrMsg = ArgBuffer.getOutOfBandError())
459
461 Caller(ArgBuffer.data(), ArgBuffer.size());
464
467 }
468
469
470
471
472
473 template <typename AsyncCallerFn, typename SendDeserializedResultFn,
474 typename... ArgTs>
475 static void callAsync(AsyncCallerFn &&Caller,
476 SendDeserializedResultFn &&SendDeserializedResult,
477 const ArgTs &...Args) {
478 using RetT = typename std::tuple_element<
480 std::remove_reference_t,
481 ResultSerializer, SPSRetTagT>::ArgTuple>::type;
482
483 auto ArgBuffer =
485 Args...);
486 if (auto *ErrMsg = ArgBuffer.getOutOfBandError()) {
487 SendDeserializedResult(
490 return;
491 }
492
493 auto SendSerializedResult = [SDR = std::move(SendDeserializedResult)](
497
498 if (auto *ErrMsg = R.getOutOfBandError()) {
500 std::move(RetVal));
501 return;
502 }
503
506 RetVal, R.data(), R.size())) {
507 SDR(std::move(Err), std::move(RetVal));
508 return;
509 }
510
512 };
513
514 Caller(std::move(SendSerializedResult), ArgBuffer.data(), ArgBuffer.size());
515 }
516
517
518 template
520 HandlerT &&Handler) {
521 using WFHH =
523 ResultSerializer, SPSTagTs...>;
524 return WFHH::apply(std::forward(Handler), ArgData, ArgSize);
525 }
526
527
528 template <typename HandlerT, typename SendResultT>
529 static void handleAsync(const char *ArgData, size_t ArgSize,
530 SendResultT &&SendResult, HandlerT &&Handler) {
532 std::remove_reference_t, ResultSerializer, SPSTagTs...>;
533 WFAHH::applyAsync(std::forward(Handler),
534 std::forward(SendResult), ArgData, ArgSize);
535 }
536
537private:
538 template static const T &makeSerializable(const T &Value) {
540 }
541
542 static detail::SPSSerializableError makeSerializable(Error Err) {
544 }
545
546 template
547 static detail::SPSSerializableExpected makeSerializable(Expected E) {
549 }
550};
551
552template <typename... SPSTagTs>
555
556public:
557 template <typename CallerFn, typename... ArgTs>
558 static Error call(const CallerFn &Caller, const ArgTs &...Args) {
561 }
562
563 template <typename AsyncCallerFn, typename SendDeserializedResultFn,
564 typename... ArgTs>
565 static void callAsync(AsyncCallerFn &&Caller,
566 SendDeserializedResultFn &&SendDeserializedResult,
567 const ArgTs &...Args) {
569 std::forward(Caller),
570 [SDR = std::move(SendDeserializedResult)](Error SerializeErr,
572 SDR(std::move(SerializeErr));
573 },
574 Args...);
575 }
576
579};
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603template <typename RetT, typename ClassT, typename... ArgTs>
605public:
606 using MethodT = RetT (ClassT::*)(ArgTs...);
609 return (ObjAddr.toPtr<ClassT*>()->*M)(std::forward(Args)...);
610 }
611
612private:
614};
615
616
617template <typename RetT, typename ClassT, typename... ArgTs>
618MethodWrapperHandler<RetT, ClassT, ArgTs...>
622
623
624
625
626
627
628
629
631public:
633
634
635
636 template <typename SPSSerializer, typename... ArgTs>
638 const ArgTs &...Args) {
640 ArgData.resize(SPSSerializer::size(Args...));
641 SPSOutputBuffer OB(ArgData.empty() ? nullptr : ArgData.data(),
642 ArgData.size());
643 if (SPSSerializer::serialize(OB, Args...))
646 "AllocActionCall",
648 }
649
651
652
654 : FnAddr(FnAddr), ArgData(std::move(ArgData)) {}
655
656
658
659
661
662
663 explicit operator bool() const { return !!FnAddr; }
664
665
667 using FnTy =
670 FnAddr.toPtr<FnTy *>()(ArgData.data(), ArgData.size()));
671 }
672
673
674 template <typename SPSRetT, typename RetT>
675 std::enable_if_t<!std::is_same<SPSRetT, void>::value, Error>
677 auto WFR = run();
678 if (const char *ErrMsg = WFR.getOutOfBandError())
683 "serialized wrapper function call",
686 }
687
688
689 template
690 std::enable_if_t<std::is_same<SPSRetT, void>::value, Error>
695
696
697
704
705private:
708};
709
711
712template <>
714public:
716 return SPSWrapperFunctionCall::AsArgList::size(WFC.getCallee(),
718 }
719
721 return SPSWrapperFunctionCall::AsArgList::serialize(OB, WFC.getCallee(),
723 }
724
728 if (!SPSWrapperFunctionCall::AsArgList::deserialize(IB, FnAddr, ArgData))
729 return false;
731 return true;
732 }
733};
734
735}
736}
737}
738
739#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Subclass of Error for the sole purpose of identifying the success path in the type system.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM Value Representation.
Represents an address in the executor process.
std::enable_if_t< std::is_pointer< T >::value, T > toPtr(WrapFn &&Wrap=WrapFn()) const
Cast this ExecutorAddr to a pointer of the given type.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.