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;
31   explicit ExecutorAddrDiff(uint64_t Value) : Value(Value) {}
32 
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 ExecutorAddr {
41 public:
42   ExecutorAddr() = default;
43   explicit ExecutorAddr(uint64_t Addr) : Addr(Addr) {}
44 
45   /// Create an ExecutorAddr from the given pointer.
46   /// Warning: This should only be used when JITing in-process.
47   template <typename T> static ExecutorAddr fromPtr(T *Value) {
48     return ExecutorAddr(
49         static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Value)));
50   }
51 
52   /// Cast this ExecutorAddr to a pointer of the given type.
53   /// Warning: This should only be esude when JITing in-process.
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 
62   uint64_t getValue() const { return Addr; }
63   void setValue(uint64_t Addr) { this->Addr = Addr; }
64   bool isNull() const { return Addr == 0; }
65 
66   explicit operator bool() const { return Addr != 0; }
67 
68   friend bool operator==(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
69     return LHS.Addr == RHS.Addr;
70   }
71 
72   friend bool operator!=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
73     return LHS.Addr != RHS.Addr;
74   }
75 
76   friend bool operator<(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
77     return LHS.Addr < RHS.Addr;
78   }
79 
80   friend bool operator<=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
81     return LHS.Addr <= RHS.Addr;
82   }
83 
84   friend bool operator>(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
85     return LHS.Addr > RHS.Addr;
86   }
87 
88   friend bool operator>=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
89     return LHS.Addr >= RHS.Addr;
90   }
91 
92   ExecutorAddr &operator++() {
93     ++Addr;
94     return *this;
95   }
96   ExecutorAddr &operator--() {
97     --Addr;
98     return *this;
99   }
100   ExecutorAddr operator++(int) { return ExecutorAddr(Addr++); }
101   ExecutorAddr operator--(int) { return ExecutorAddr(Addr++); }
102 
103   ExecutorAddr &operator+=(const ExecutorAddrDiff Delta) {
104     Addr += Delta.getValue();
105     return *this;
106   }
107 
108   ExecutorAddr &operator-=(const ExecutorAddrDiff Delta) {
109     Addr -= Delta.getValue();
110     return *this;
111   }
112 
113 private:
114   uint64_t Addr = 0;
115 };
116 
117 /// Subtracting two addresses yields an offset.
118 inline ExecutorAddrDiff operator-(const ExecutorAddr &LHS,
119                                   const ExecutorAddr &RHS) {
120   return ExecutorAddrDiff(LHS.getValue() - RHS.getValue());
121 }
122 
123 /// Adding an offset and an address yields an address.
124 inline ExecutorAddr operator+(const ExecutorAddr &LHS,
125                               const ExecutorAddrDiff &RHS) {
126   return ExecutorAddr(LHS.getValue() + RHS.getValue());
127 }
128 
129 /// Adding an address and an offset yields an address.
130 inline ExecutorAddr operator+(const ExecutorAddrDiff &LHS,
131                               const ExecutorAddr &RHS) {
132   return ExecutorAddr(LHS.getValue() + RHS.getValue());
133 }
134 
135 /// Represents an address range in the exceutor process.
136 struct ExecutorAddrRange {
137   ExecutorAddrRange() = default;
138   ExecutorAddrRange(ExecutorAddr StartAddress, ExecutorAddr EndAddress)
139       : StartAddress(StartAddress), EndAddress(EndAddress) {}
140 
141   bool empty() const { return StartAddress == EndAddress; }
142   ExecutorAddrDiff size() const { return EndAddress - StartAddress; }
143 
144   template <typename T> span<T> toSpan() const {
145     assert(size().getValue() % sizeof(T) == 0 &&
146            "AddressRange is not a multiple of sizeof(T)");
147     return span<T>(StartAddress.toPtr<T *>(), size().getValue() / sizeof(T));
148   }
149 
150   ExecutorAddr StartAddress;
151   ExecutorAddr EndAddress;
152 };
153 
154 /// SPS serializatior for ExecutorAddr.
155 template <> class SPSSerializationTraits<SPSExecutorAddr, ExecutorAddr> {
156 public:
157   static size_t size(const ExecutorAddr &EA) {
158     return SPSArgList<uint64_t>::size(EA.getValue());
159   }
160 
161   static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddr &EA) {
162     return SPSArgList<uint64_t>::serialize(BOB, EA.getValue());
163   }
164 
165   static bool deserialize(SPSInputBuffer &BIB, ExecutorAddr &EA) {
166     uint64_t Tmp;
167     if (!SPSArgList<uint64_t>::deserialize(BIB, Tmp))
168       return false;
169     EA = ExecutorAddr(Tmp);
170     return true;
171   }
172 };
173 
174 using SPSExecutorAddrRange = SPSTuple<SPSExecutorAddr, SPSExecutorAddr>;
175 
176 /// Serialization traits for address ranges.
177 template <>
178 class SPSSerializationTraits<SPSExecutorAddrRange, ExecutorAddrRange> {
179 public:
180   static size_t size(const ExecutorAddrRange &Value) {
181     return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::size(
182         Value.StartAddress, Value.EndAddress);
183   }
184 
185   static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddrRange &Value) {
186     return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::serialize(
187         BOB, Value.StartAddress, Value.EndAddress);
188   }
189 
190   static bool deserialize(SPSInputBuffer &BIB, ExecutorAddrRange &Value) {
191     return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::deserialize(
192         BIB, Value.StartAddress, Value.EndAddress);
193   }
194 };
195 
196 using SPSExecutorAddrRangeSequence = SPSSequence<SPSExecutorAddrRange>;
197 
198 } // End namespace __orc_rt
199 
200 #endif // ORC_RT_EXECUTOR_ADDRESS_H
201