ExecutorAddress.h 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===------ ExecutorAddress.h - Executing process address -------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // Represents an address in the executing program.
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H
  18. #define LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H
  19. #include "llvm/ADT/DenseMapInfo.h"
  20. #include "llvm/ADT/identity.h"
  21. #include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h"
  22. #include "llvm/Support/FormatVariadic.h"
  23. #include "llvm/Support/raw_ostream.h"
  24. #include <cassert>
  25. #include <type_traits>
  26. namespace llvm {
  27. namespace orc {
  28. using ExecutorAddrDiff = uint64_t;
  29. /// Represents an address in the executor process.
  30. class ExecutorAddr {
  31. public:
  32. /// A wrap/unwrap function that leaves pointers unmodified.
  33. template <typename T> using rawPtr = llvm::identity<T *>;
  34. /// Default wrap function to use on this host.
  35. template <typename T> using defaultWrap = rawPtr<T>;
  36. /// Default unwrap function to use on this host.
  37. template <typename T> using defaultUnwrap = rawPtr<T>;
  38. /// Merges a tag into the raw address value:
  39. /// P' = P | (TagValue << TagOffset).
  40. class Tag {
  41. public:
  42. constexpr Tag(uintptr_t TagValue, uintptr_t TagOffset)
  43. : TagMask(TagValue << TagOffset) {}
  44. template <typename T> constexpr T *operator()(T *P) {
  45. return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) | TagMask);
  46. }
  47. private:
  48. uintptr_t TagMask;
  49. };
  50. /// Strips a tag of the given length from the given offset within the pointer:
  51. /// P' = P & ~(((1 << TagLen) -1) << TagOffset)
  52. class Untag {
  53. public:
  54. constexpr Untag(uintptr_t TagLen, uintptr_t TagOffset)
  55. : UntagMask(~(((uintptr_t(1) << TagLen) - 1) << TagOffset)) {}
  56. template <typename T> constexpr T *operator()(T *P) {
  57. return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) & UntagMask);
  58. }
  59. private:
  60. uintptr_t UntagMask;
  61. };
  62. ExecutorAddr() = default;
  63. /// Create an ExecutorAddr from the given value.
  64. explicit constexpr ExecutorAddr(uint64_t Addr) : Addr(Addr) {}
  65. /// Create an ExecutorAddr from the given pointer.
  66. /// Warning: This should only be used when JITing in-process.
  67. template <typename T, typename UnwrapFn = defaultUnwrap<T>>
  68. static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap = UnwrapFn()) {
  69. return ExecutorAddr(
  70. static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Unwrap(Ptr))));
  71. }
  72. /// Cast this ExecutorAddr to a pointer of the given type.
  73. /// Warning: This should only be used when JITing in-process.
  74. template <typename T, typename WrapFn = defaultWrap<std::remove_pointer_t<T>>>
  75. std::enable_if_t<std::is_pointer<T>::value, T>
  76. toPtr(WrapFn &&Wrap = WrapFn()) const {
  77. uintptr_t IntPtr = static_cast<uintptr_t>(Addr);
  78. assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t");
  79. return Wrap(reinterpret_cast<T>(IntPtr));
  80. }
  81. /// Cast this ExecutorAddr to a pointer of the given function type.
  82. /// Warning: This should only be used when JITing in-process.
  83. template <typename T, typename WrapFn = defaultWrap<T>>
  84. std::enable_if_t<std::is_function<T>::value, T *>
  85. toPtr(WrapFn &&Wrap = WrapFn()) const {
  86. uintptr_t IntPtr = static_cast<uintptr_t>(Addr);
  87. assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t");
  88. return Wrap(reinterpret_cast<T *>(IntPtr));
  89. }
  90. uint64_t getValue() const { return Addr; }
  91. void setValue(uint64_t Addr) { this->Addr = Addr; }
  92. bool isNull() const { return Addr == 0; }
  93. explicit operator bool() const { return Addr != 0; }
  94. friend bool operator==(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
  95. return LHS.Addr == RHS.Addr;
  96. }
  97. friend bool operator!=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
  98. return LHS.Addr != RHS.Addr;
  99. }
  100. friend bool operator<(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
  101. return LHS.Addr < RHS.Addr;
  102. }
  103. friend bool operator<=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
  104. return LHS.Addr <= RHS.Addr;
  105. }
  106. friend bool operator>(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
  107. return LHS.Addr > RHS.Addr;
  108. }
  109. friend bool operator>=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {
  110. return LHS.Addr >= RHS.Addr;
  111. }
  112. ExecutorAddr &operator++() {
  113. ++Addr;
  114. return *this;
  115. }
  116. ExecutorAddr &operator--() {
  117. --Addr;
  118. return *this;
  119. }
  120. ExecutorAddr operator++(int) { return ExecutorAddr(Addr++); }
  121. ExecutorAddr operator--(int) { return ExecutorAddr(Addr--); }
  122. ExecutorAddr &operator+=(const ExecutorAddrDiff &Delta) {
  123. Addr += Delta;
  124. return *this;
  125. }
  126. ExecutorAddr &operator-=(const ExecutorAddrDiff &Delta) {
  127. Addr -= Delta;
  128. return *this;
  129. }
  130. private:
  131. uint64_t Addr = 0;
  132. };
  133. /// Subtracting two addresses yields an offset.
  134. inline ExecutorAddrDiff operator-(const ExecutorAddr &LHS,
  135. const ExecutorAddr &RHS) {
  136. return ExecutorAddrDiff(LHS.getValue() - RHS.getValue());
  137. }
  138. /// Adding an offset and an address yields an address.
  139. inline ExecutorAddr operator+(const ExecutorAddr &LHS,
  140. const ExecutorAddrDiff &RHS) {
  141. return ExecutorAddr(LHS.getValue() + RHS);
  142. }
  143. /// Adding an address and an offset yields an address.
  144. inline ExecutorAddr operator+(const ExecutorAddrDiff &LHS,
  145. const ExecutorAddr &RHS) {
  146. return ExecutorAddr(LHS + RHS.getValue());
  147. }
  148. /// Subtracting an offset from an address yields an address.
  149. inline ExecutorAddr operator-(const ExecutorAddr &LHS,
  150. const ExecutorAddrDiff &RHS) {
  151. return ExecutorAddr(LHS.getValue() - RHS);
  152. }
  153. /// Taking the modulus of an address and a diff yields a diff.
  154. inline ExecutorAddrDiff operator%(const ExecutorAddr &LHS,
  155. const ExecutorAddrDiff &RHS) {
  156. return ExecutorAddrDiff(LHS.getValue() % RHS);
  157. }
  158. /// Represents an address range in the exceutor process.
  159. struct ExecutorAddrRange {
  160. ExecutorAddrRange() = default;
  161. ExecutorAddrRange(ExecutorAddr Start, ExecutorAddr End)
  162. : Start(Start), End(End) {}
  163. ExecutorAddrRange(ExecutorAddr Start, ExecutorAddrDiff Size)
  164. : Start(Start), End(Start + Size) {}
  165. bool empty() const { return Start == End; }
  166. ExecutorAddrDiff size() const { return End - Start; }
  167. friend bool operator==(const ExecutorAddrRange &LHS,
  168. const ExecutorAddrRange &RHS) {
  169. return LHS.Start == RHS.Start && LHS.End == RHS.End;
  170. }
  171. friend bool operator!=(const ExecutorAddrRange &LHS,
  172. const ExecutorAddrRange &RHS) {
  173. return !(LHS == RHS);
  174. }
  175. bool contains(ExecutorAddr Addr) const { return Start <= Addr && Addr < End; }
  176. bool overlaps(const ExecutorAddrRange &Other) {
  177. return !(Other.End <= Start || End <= Other.Start);
  178. }
  179. ExecutorAddr Start;
  180. ExecutorAddr End;
  181. };
  182. inline raw_ostream &operator<<(raw_ostream &OS, const ExecutorAddr &A) {
  183. return OS << formatv("{0:x}", A.getValue());
  184. }
  185. inline raw_ostream &operator<<(raw_ostream &OS, const ExecutorAddrRange &R) {
  186. return OS << formatv("{0:x} -- {1:x}", R.Start.getValue(), R.End.getValue());
  187. }
  188. namespace shared {
  189. class SPSExecutorAddr {};
  190. /// SPS serializatior for ExecutorAddr.
  191. template <> class SPSSerializationTraits<SPSExecutorAddr, ExecutorAddr> {
  192. public:
  193. static size_t size(const ExecutorAddr &EA) {
  194. return SPSArgList<uint64_t>::size(EA.getValue());
  195. }
  196. static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddr &EA) {
  197. return SPSArgList<uint64_t>::serialize(BOB, EA.getValue());
  198. }
  199. static bool deserialize(SPSInputBuffer &BIB, ExecutorAddr &EA) {
  200. uint64_t Tmp;
  201. if (!SPSArgList<uint64_t>::deserialize(BIB, Tmp))
  202. return false;
  203. EA = ExecutorAddr(Tmp);
  204. return true;
  205. }
  206. };
  207. using SPSExecutorAddrRange = SPSTuple<SPSExecutorAddr, SPSExecutorAddr>;
  208. /// Serialization traits for address ranges.
  209. template <>
  210. class SPSSerializationTraits<SPSExecutorAddrRange, ExecutorAddrRange> {
  211. public:
  212. static size_t size(const ExecutorAddrRange &Value) {
  213. return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::size(Value.Start,
  214. Value.End);
  215. }
  216. static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddrRange &Value) {
  217. return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::serialize(
  218. BOB, Value.Start, Value.End);
  219. }
  220. static bool deserialize(SPSInputBuffer &BIB, ExecutorAddrRange &Value) {
  221. return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::deserialize(
  222. BIB, Value.Start, Value.End);
  223. }
  224. };
  225. using SPSExecutorAddrRangeSequence = SPSSequence<SPSExecutorAddrRange>;
  226. } // End namespace shared.
  227. } // End namespace orc.
  228. // Provide DenseMapInfo for ExecutorAddrs.
  229. template <> struct DenseMapInfo<orc::ExecutorAddr> {
  230. static inline orc::ExecutorAddr getEmptyKey() {
  231. return orc::ExecutorAddr(DenseMapInfo<uint64_t>::getEmptyKey());
  232. }
  233. static inline orc::ExecutorAddr getTombstoneKey() {
  234. return orc::ExecutorAddr(DenseMapInfo<uint64_t>::getTombstoneKey());
  235. }
  236. static unsigned getHashValue(const orc::ExecutorAddr &Addr) {
  237. return DenseMapInfo<uint64_t>::getHashValue(Addr.getValue());
  238. }
  239. static bool isEqual(const orc::ExecutorAddr &LHS,
  240. const orc::ExecutorAddr &RHS) {
  241. return DenseMapInfo<uint64_t>::isEqual(LHS.getValue(), RHS.getValue());
  242. }
  243. };
  244. } // End namespace llvm.
  245. #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H
  246. #ifdef __GNUC__
  247. #pragma GCC diagnostic pop
  248. #endif