1 //===--- TargetProcessControlTypes.h -- Shared Core/TPC types ---*- C++ -*-===//
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 // TargetProcessControl types that are used by both the Orc and
10 // OrcTargetProcess libraries.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_TARGETPROCESSCONTROLTYPES_H
15 #define LLVM_EXECUTIONENGINE_ORC_SHARED_TARGETPROCESSCONTROLTYPES_H
16 
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ExecutionEngine/JITSymbol.h"
20 
21 #include <vector>
22 
23 namespace llvm {
24 namespace orc {
25 namespace tpctypes {
26 
27 template <typename T> struct UIntWrite {
28   UIntWrite() = default;
UIntWriteUIntWrite29   UIntWrite(JITTargetAddress Address, T Value)
30       : Address(Address), Value(Value) {}
31 
32   JITTargetAddress Address = 0;
33   T Value = 0;
34 };
35 
36 /// Describes a write to a uint8_t.
37 using UInt8Write = UIntWrite<uint8_t>;
38 
39 /// Describes a write to a uint16_t.
40 using UInt16Write = UIntWrite<uint16_t>;
41 
42 /// Describes a write to a uint32_t.
43 using UInt32Write = UIntWrite<uint32_t>;
44 
45 /// Describes a write to a uint64_t.
46 using UInt64Write = UIntWrite<uint64_t>;
47 
48 /// Describes a write to a buffer.
49 /// For use with TargetProcessControl::MemoryAccess objects.
50 struct BufferWrite {
51   BufferWrite() = default;
BufferWriteBufferWrite52   BufferWrite(JITTargetAddress Address, StringRef Buffer)
53       : Address(Address), Buffer(Buffer) {}
54 
55   JITTargetAddress Address = 0;
56   StringRef Buffer;
57 };
58 
59 /// A handle used to represent a loaded dylib in the target process.
60 using DylibHandle = JITTargetAddress;
61 
62 using LookupResult = std::vector<JITTargetAddress>;
63 
64 /// Either a uint8_t array or a uint8_t*.
65 union CWrapperFunctionResultData {
66   uint8_t Value[8];
67   uint8_t *ValuePtr;
68 };
69 
70 /// C ABI compatible wrapper function result.
71 ///
72 /// This can be safely returned from extern "C" functions, but should be used
73 /// to construct a WrapperFunctionResult for safety.
74 struct CWrapperFunctionResult {
75   uint64_t Size;
76   CWrapperFunctionResultData Data;
77   void (*Destroy)(CWrapperFunctionResultData Data, uint64_t Size);
78 };
79 
80 /// C++ wrapper function result: Same as CWrapperFunctionResult but
81 /// auto-releases memory.
82 class WrapperFunctionResult {
83 public:
84   /// Create a default WrapperFunctionResult.
WrapperFunctionResult()85   WrapperFunctionResult() { zeroInit(R); }
86 
87   /// Create a WrapperFunctionResult from a CWrapperFunctionResult. This
88   /// instance takes ownership of the result object and will automatically
89   /// call the Destroy member upon destruction.
WrapperFunctionResult(CWrapperFunctionResult R)90   WrapperFunctionResult(CWrapperFunctionResult R) : R(R) {}
91 
92   WrapperFunctionResult(const WrapperFunctionResult &) = delete;
93   WrapperFunctionResult &operator=(const WrapperFunctionResult &) = delete;
94 
WrapperFunctionResult(WrapperFunctionResult && Other)95   WrapperFunctionResult(WrapperFunctionResult &&Other) {
96     zeroInit(R);
97     std::swap(R, Other.R);
98   }
99 
100   WrapperFunctionResult &operator=(WrapperFunctionResult &&Other) {
101     CWrapperFunctionResult Tmp;
102     zeroInit(Tmp);
103     std::swap(Tmp, Other.R);
104     std::swap(R, Tmp);
105     return *this;
106   }
107 
~WrapperFunctionResult()108   ~WrapperFunctionResult() {
109     if (R.Destroy)
110       R.Destroy(R.Data, R.Size);
111   }
112 
113   /// Relinquish ownership of and return the CWrapperFunctionResult.
release()114   CWrapperFunctionResult release() {
115     CWrapperFunctionResult Tmp;
116     zeroInit(Tmp);
117     std::swap(R, Tmp);
118     return Tmp;
119   }
120 
121   /// Get an ArrayRef covering the data in the result.
getData()122   ArrayRef<uint8_t> getData() const {
123     if (R.Size <= 8)
124       return ArrayRef<uint8_t>(R.Data.Value, R.Size);
125     return ArrayRef<uint8_t>(R.Data.ValuePtr, R.Size);
126   }
127 
128   /// Create a WrapperFunctionResult from the given integer, provided its
129   /// size is no greater than 64 bits.
130   template <typename T,
131             typename _ = std::enable_if_t<std::is_integral<T>::value &&
132                                           sizeof(T) <= sizeof(uint64_t)>>
from(T Value)133   static WrapperFunctionResult from(T Value) {
134     CWrapperFunctionResult R;
135     R.Size = sizeof(T);
136     memcpy(&R.Data.Value, Value, R.Size);
137     R.Destroy = nullptr;
138     return R;
139   }
140 
141   /// Create a WrapperFunctionResult from the given string.
142   static WrapperFunctionResult from(StringRef S);
143 
144   /// Always free Data.ValuePtr by calling free on it.
145   static void destroyWithFree(CWrapperFunctionResultData Data, uint64_t Size);
146 
147   /// Always free Data.ValuePtr by calling delete[] on it.
148   static void destroyWithDeleteArray(CWrapperFunctionResultData Data,
149                                      uint64_t Size);
150 
151 private:
zeroInit(CWrapperFunctionResult & R)152   static void zeroInit(CWrapperFunctionResult &R) {
153     R.Size = 0;
154     R.Data.ValuePtr = nullptr;
155     R.Destroy = nullptr;
156   }
157 
158   CWrapperFunctionResult R;
159 };
160 
161 } // end namespace tpctypes
162 } // end namespace orc
163 } // end namespace llvm
164 
165 #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_TARGETPROCESSCONTROLTYPES_H
166