1 //===------ ExecutorAddress.h - Executing process address -------*- 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 // Represents an address in the executing program.
10 //
11 // This file was derived from
12 // llvm/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #ifndef ORC_RT_EXECUTOR_ADDRESS_H
17 #define ORC_RT_EXECUTOR_ADDRESS_H
18 
19 #include "adt.h"
20 #include "simple_packed_serialization.h"
21 
22 #include <cassert>
23 #include <type_traits>
24 
25 namespace __orc_rt {
26 
27 /// Represents the difference between two addresses in the executor process.
28 class ExecutorAddrDiff {
29 public:
30   ExecutorAddrDiff() = default;
ExecutorAddrDiff(uint64_t Value)31   explicit ExecutorAddrDiff(uint64_t Value) : Value(Value) {}
32 
getValue()33   uint64_t getValue() const { return Value; }
34 
35 private:
36   int64_t Value = 0;
37 };
38 
39 /// Represents an address in the executor process.
40 class ExecutorAddress {
41 public:
42   ExecutorAddress() = default;
ExecutorAddress(uint64_t Addr)43   explicit ExecutorAddress(uint64_t Addr) : Addr(Addr) {}
44 
45   /// Create an ExecutorAddress from the given pointer.
46   /// Warning: This should only be used when JITing in-process.
fromPtr(T * Value)47   template <typename T> static ExecutorAddress fromPtr(T *Value) {
48     return ExecutorAddress(
49         static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Value)));
50   }
51 
52   /// Cast this ExecutorAddress to a pointer of the given type.
53   /// Warning: This should only be esude when JITing in-process.
toPtr()54   template <typename T> T toPtr() const {
55     static_assert(std::is_pointer<T>::value, "T must be a pointer type");
56     uintptr_t IntPtr = static_cast<uintptr_t>(Addr);
57     assert(IntPtr == Addr &&
58            "JITTargetAddress value out of range for uintptr_t");
59     return reinterpret_cast<T>(IntPtr);
60   }
61 
getValue()62   uint64_t getValue() const { return Addr; }
setValue(uint64_t Addr)63   void setValue(uint64_t Addr) { this->Addr = Addr; }
isNull()64   bool isNull() const { return Addr == 0; }
65 
66   explicit operator bool() const { return Addr != 0; }
67 
68   friend bool operator==(const ExecutorAddress &LHS,
69                          const ExecutorAddress &RHS) {
70     return LHS.Addr == RHS.Addr;
71   }
72 
73   friend bool operator!=(const ExecutorAddress &LHS,
74                          const ExecutorAddress &RHS) {
75     return LHS.Addr != RHS.Addr;
76   }
77 
78   friend bool operator<(const ExecutorAddress &LHS,
79                         const ExecutorAddress &RHS) {
80     return LHS.Addr < RHS.Addr;
81   }
82 
83   friend bool operator<=(const ExecutorAddress &LHS,
84                          const ExecutorAddress &RHS) {
85     return LHS.Addr <= RHS.Addr;
86   }
87 
88   friend bool operator>(const ExecutorAddress &LHS,
89                         const ExecutorAddress &RHS) {
90     return LHS.Addr > RHS.Addr;
91   }
92 
93   friend bool operator>=(const ExecutorAddress &LHS,
94                          const ExecutorAddress &RHS) {
95     return LHS.Addr >= RHS.Addr;
96   }
97 
98   ExecutorAddress &operator++() {
99     ++Addr;
100     return *this;
101   }
102   ExecutorAddress &operator--() {
103     --Addr;
104     return *this;
105   }
106   ExecutorAddress operator++(int) { return ExecutorAddress(Addr++); }
107   ExecutorAddress operator--(int) { return ExecutorAddress(Addr++); }
108 
109   ExecutorAddress &operator+=(const ExecutorAddrDiff Delta) {
110     Addr += Delta.getValue();
111     return *this;
112   }
113 
114   ExecutorAddress &operator-=(const ExecutorAddrDiff Delta) {
115     Addr -= Delta.getValue();
116     return *this;
117   }
118 
119 private:
120   uint64_t Addr = 0;
121 };
122 
123 /// Subtracting two addresses yields an offset.
124 inline ExecutorAddrDiff operator-(const ExecutorAddress &LHS,
125                                   const ExecutorAddress &RHS) {
126   return ExecutorAddrDiff(LHS.getValue() - RHS.getValue());
127 }
128 
129 /// Adding an offset and an address yields an address.
130 inline ExecutorAddress operator+(const ExecutorAddress &LHS,
131                                  const ExecutorAddrDiff &RHS) {
132   return ExecutorAddress(LHS.getValue() + RHS.getValue());
133 }
134 
135 /// Adding an address and an offset yields an address.
136 inline ExecutorAddress operator+(const ExecutorAddrDiff &LHS,
137                                  const ExecutorAddress &RHS) {
138   return ExecutorAddress(LHS.getValue() + RHS.getValue());
139 }
140 
141 /// Represents an address range in the exceutor process.
142 struct ExecutorAddressRange {
143   ExecutorAddressRange() = default;
ExecutorAddressRangeExecutorAddressRange144   ExecutorAddressRange(ExecutorAddress StartAddress, ExecutorAddress EndAddress)
145       : StartAddress(StartAddress), EndAddress(EndAddress) {}
146 
emptyExecutorAddressRange147   bool empty() const { return StartAddress == EndAddress; }
sizeExecutorAddressRange148   ExecutorAddrDiff size() const { return EndAddress - StartAddress; }
149 
toSpanExecutorAddressRange150   template <typename T> span<T> toSpan() const {
151     assert(size().getValue() % sizeof(T) == 0 &&
152            "AddressRange is not a multiple of sizeof(T)");
153     return span<T>(StartAddress.toPtr<T *>(), size().getValue() / sizeof(T));
154   }
155 
156   ExecutorAddress StartAddress;
157   ExecutorAddress EndAddress;
158 };
159 
160 /// SPS serializatior for ExecutorAddress.
161 template <> class SPSSerializationTraits<SPSExecutorAddress, ExecutorAddress> {
162 public:
size(const ExecutorAddress & EA)163   static size_t size(const ExecutorAddress &EA) {
164     return SPSArgList<uint64_t>::size(EA.getValue());
165   }
166 
serialize(SPSOutputBuffer & BOB,const ExecutorAddress & EA)167   static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddress &EA) {
168     return SPSArgList<uint64_t>::serialize(BOB, EA.getValue());
169   }
170 
deserialize(SPSInputBuffer & BIB,ExecutorAddress & EA)171   static bool deserialize(SPSInputBuffer &BIB, ExecutorAddress &EA) {
172     uint64_t Tmp;
173     if (!SPSArgList<uint64_t>::deserialize(BIB, Tmp))
174       return false;
175     EA = ExecutorAddress(Tmp);
176     return true;
177   }
178 };
179 
180 using SPSExecutorAddressRange =
181     SPSTuple<SPSExecutorAddress, SPSExecutorAddress>;
182 
183 /// Serialization traits for address ranges.
184 template <>
185 class SPSSerializationTraits<SPSExecutorAddressRange, ExecutorAddressRange> {
186 public:
size(const ExecutorAddressRange & Value)187   static size_t size(const ExecutorAddressRange &Value) {
188     return SPSArgList<SPSExecutorAddress, SPSExecutorAddress>::size(
189         Value.StartAddress, Value.EndAddress);
190   }
191 
serialize(SPSOutputBuffer & BOB,const ExecutorAddressRange & Value)192   static bool serialize(SPSOutputBuffer &BOB,
193                         const ExecutorAddressRange &Value) {
194     return SPSArgList<SPSExecutorAddress, SPSExecutorAddress>::serialize(
195         BOB, Value.StartAddress, Value.EndAddress);
196   }
197 
deserialize(SPSInputBuffer & BIB,ExecutorAddressRange & Value)198   static bool deserialize(SPSInputBuffer &BIB, ExecutorAddressRange &Value) {
199     return SPSArgList<SPSExecutorAddress, SPSExecutorAddress>::deserialize(
200         BIB, Value.StartAddress, Value.EndAddress);
201   }
202 };
203 
204 using SPSExecutorAddressRangeSequence = SPSSequence<SPSExecutorAddressRange>;
205 
206 } // End namespace __orc_rt
207 
208 #endif // ORC_RT_EXECUTOR_ADDRESS_H
209