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