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

94 const char *data() const {

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.