1 | //===- helpers.hpp- GetInfo return helpers for the new LLVM/Offload API ---===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // The getInfo*/ReturnHelper facilities provide shortcut way of writing return |
10 | // data + size for the various getInfo APIs. Based on the equivalent |
11 | // implementations in Unified Runtime. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #include "OffloadAPI.h" |
16 | #include "OffloadError.h" |
17 | #include "llvm/Support/Error.h" |
18 | |
19 | #include <cstring> |
20 | |
21 | template <typename T, typename Assign> |
22 | llvm::Error getInfoImpl(size_t ParamValueSize, void *ParamValue, |
23 | size_t *ParamValueSizeRet, T Value, size_t ValueSize, |
24 | Assign &&AssignFunc) { |
25 | if (!ParamValue && !ParamValueSizeRet) { |
26 | return error::createOffloadError(error::ErrorCode::INVALID_NULL_POINTER, |
27 | "value and size outputs are nullptr" ); |
28 | } |
29 | |
30 | if (ParamValue != nullptr) { |
31 | if (ParamValueSize < ValueSize) { |
32 | return error::createOffloadError(error::ErrorCode::INVALID_SIZE, |
33 | "provided size is invalid" ); |
34 | } |
35 | AssignFunc(ParamValue, Value, ValueSize); |
36 | } |
37 | |
38 | if (ParamValueSizeRet != nullptr) { |
39 | *ParamValueSizeRet = ValueSize; |
40 | } |
41 | |
42 | return llvm::Error::success(); |
43 | } |
44 | |
45 | template <typename T> |
46 | llvm::Error getInfo(size_t ParamValueSize, void *ParamValue, |
47 | size_t *ParamValueSizeRet, T Value) { |
48 | auto Assignment = [](void *ParamValue, T Value, size_t) { |
49 | *static_cast<T *>(ParamValue) = Value; |
50 | }; |
51 | |
52 | return getInfoImpl(ParamValueSize, ParamValue, ParamValueSizeRet, Value, |
53 | sizeof(T), Assignment); |
54 | } |
55 | |
56 | template <typename T> |
57 | llvm::Error getInfoArray(size_t array_length, size_t ParamValueSize, |
58 | void *ParamValue, size_t *ParamValueSizeRet, |
59 | const T *Value) { |
60 | return getInfoImpl(ParamValueSize, ParamValue, ParamValueSizeRet, Value, |
61 | array_length * sizeof(T), memcpy); |
62 | } |
63 | |
64 | template <> |
65 | inline llvm::Error |
66 | getInfo<const char *>(size_t ParamValueSize, void *ParamValue, |
67 | size_t *ParamValueSizeRet, const char *Value) { |
68 | return getInfoArray(array_length: strlen(s: Value) + 1, ParamValueSize, ParamValue, |
69 | ParamValueSizeRet, Value); |
70 | } |
71 | |
72 | class ReturnHelper { |
73 | public: |
74 | ReturnHelper(size_t ParamValueSize, void *ParamValue, |
75 | size_t *ParamValueSizeRet) |
76 | : ParamValueSize(ParamValueSize), ParamValue(ParamValue), |
77 | ParamValueSizeRet(ParamValueSizeRet) {} |
78 | |
79 | // A version where in/out info size is represented by a single pointer |
80 | // to a value which is updated on return |
81 | ReturnHelper(size_t *ParamValueSize, void *ParamValue) |
82 | : ParamValueSize(*ParamValueSize), ParamValue(ParamValue), |
83 | ParamValueSizeRet(ParamValueSize) {} |
84 | |
85 | // Scalar return Value |
86 | template <class T> llvm::Error operator()(const T &t) { |
87 | return getInfo(ParamValueSize, ParamValue, ParamValueSizeRet, t); |
88 | } |
89 | |
90 | // Array return Value |
91 | template <class T> llvm::Error operator()(const T *t, size_t s) { |
92 | return getInfoArray(s, ParamValueSize, ParamValue, ParamValueSizeRet, t); |
93 | } |
94 | |
95 | protected: |
96 | size_t ParamValueSize; |
97 | void *ParamValue; |
98 | size_t *ParamValueSizeRet; |
99 | }; |
100 | |