Path: blob/main/contrib/llvm-project/compiler-rt/lib/orc/executor_address.h
39566 views
//===------ ExecutorAddress.h - Executing process address -------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Represents an address in the executing program.9//10// This file was derived from11// llvm/include/llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h.12//13//===----------------------------------------------------------------------===//1415#ifndef ORC_RT_EXECUTOR_ADDRESS_H16#define ORC_RT_EXECUTOR_ADDRESS_H1718#include "adt.h"19#include "simple_packed_serialization.h"2021#include <cassert>22#include <type_traits>2324namespace __orc_rt {2526using ExecutorAddrDiff = uint64_t;2728/// Represents an address in the executor process.29class ExecutorAddr {30public:31/// A wrap/unwrap function that leaves pointers unmodified.32template <typename T> using rawPtr = __orc_rt::identity<T *>;3334/// Default wrap function to use on this host.35template <typename T> using defaultWrap = rawPtr<T>;3637/// Default unwrap function to use on this host.38template <typename T> using defaultUnwrap = rawPtr<T>;3940/// Merges a tag into the raw address value:41/// P' = P | (TagValue << TagOffset).42class Tag {43public:44constexpr Tag(uintptr_t TagValue, uintptr_t TagOffset)45: TagMask(TagValue << TagOffset) {}4647template <typename T> constexpr T *operator()(T *P) {48return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) | TagMask);49}5051private:52uintptr_t TagMask;53};5455/// Strips a tag of the given length from the given offset within the pointer:56/// P' = P & ~(((1 << TagLen) -1) << TagOffset)57class Untag {58public:59constexpr Untag(uintptr_t TagLen, uintptr_t TagOffset)60: UntagMask(~(((uintptr_t(1) << TagLen) - 1) << TagOffset)) {}6162template <typename T> constexpr T *operator()(T *P) {63return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) & UntagMask);64}6566private:67uintptr_t UntagMask;68};6970ExecutorAddr() = default;71explicit ExecutorAddr(uint64_t Addr) : Addr(Addr) {}7273/// Create an ExecutorAddr from the given pointer.74template <typename T, typename UnwrapFn = defaultUnwrap<T>>75static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap = UnwrapFn()) {76return ExecutorAddr(77static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Unwrap(Ptr))));78}7980/// Cast this ExecutorAddr to a pointer of the given type.81template <typename T, typename WrapFn = defaultWrap<std::remove_pointer_t<T>>>82std::enable_if_t<std::is_pointer<T>::value, T>83toPtr(WrapFn &&Wrap = WrapFn()) const {84uintptr_t IntPtr = static_cast<uintptr_t>(Addr);85assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t");86return Wrap(reinterpret_cast<T>(IntPtr));87}8889/// Cast this ExecutorAddr to a pointer of the given function type.90template <typename T, typename WrapFn = defaultWrap<T>>91std::enable_if_t<std::is_function<T>::value, T *>92toPtr(WrapFn &&Wrap = WrapFn()) const {93uintptr_t IntPtr = static_cast<uintptr_t>(Addr);94assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t");95return Wrap(reinterpret_cast<T *>(IntPtr));96}9798uint64_t getValue() const { return Addr; }99void setValue(uint64_t Addr) { this->Addr = Addr; }100bool isNull() const { return Addr == 0; }101102explicit operator bool() const { return Addr != 0; }103104friend bool operator==(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {105return LHS.Addr == RHS.Addr;106}107108friend bool operator!=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {109return LHS.Addr != RHS.Addr;110}111112friend bool operator<(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {113return LHS.Addr < RHS.Addr;114}115116friend bool operator<=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {117return LHS.Addr <= RHS.Addr;118}119120friend bool operator>(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {121return LHS.Addr > RHS.Addr;122}123124friend bool operator>=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) {125return LHS.Addr >= RHS.Addr;126}127128ExecutorAddr &operator++() {129++Addr;130return *this;131}132ExecutorAddr &operator--() {133--Addr;134return *this;135}136ExecutorAddr operator++(int) { return ExecutorAddr(Addr++); }137ExecutorAddr operator--(int) { return ExecutorAddr(Addr++); }138139ExecutorAddr &operator+=(const ExecutorAddrDiff Delta) {140Addr += Delta;141return *this;142}143144ExecutorAddr &operator-=(const ExecutorAddrDiff Delta) {145Addr -= Delta;146return *this;147}148149private:150uint64_t Addr = 0;151};152153/// Subtracting two addresses yields an offset.154inline ExecutorAddrDiff operator-(const ExecutorAddr &LHS,155const ExecutorAddr &RHS) {156return ExecutorAddrDiff(LHS.getValue() - RHS.getValue());157}158159/// Adding an offset and an address yields an address.160inline ExecutorAddr operator+(const ExecutorAddr &LHS,161const ExecutorAddrDiff &RHS) {162return ExecutorAddr(LHS.getValue() + RHS);163}164165/// Adding an address and an offset yields an address.166inline ExecutorAddr operator+(const ExecutorAddrDiff &LHS,167const ExecutorAddr &RHS) {168return ExecutorAddr(LHS + RHS.getValue());169}170171/// Represents an address range in the exceutor process.172struct ExecutorAddrRange {173ExecutorAddrRange() = default;174ExecutorAddrRange(ExecutorAddr Start, ExecutorAddr End)175: Start(Start), End(End) {}176ExecutorAddrRange(ExecutorAddr Start, ExecutorAddrDiff Size)177: Start(Start), End(Start + Size) {}178179bool empty() const { return Start == End; }180ExecutorAddrDiff size() const { return End - Start; }181182friend bool operator==(const ExecutorAddrRange &LHS,183const ExecutorAddrRange &RHS) {184return LHS.Start == RHS.Start && LHS.End == RHS.End;185}186friend bool operator!=(const ExecutorAddrRange &LHS,187const ExecutorAddrRange &RHS) {188return !(LHS == RHS);189}190bool contains(ExecutorAddr Addr) const { return Start <= Addr && Addr < End; }191bool overlaps(const ExecutorAddrRange &Other) {192return !(Other.End <= Start || End <= Other.Start);193}194195template <typename T> span<T> toSpan() const {196assert(size() % sizeof(T) == 0 &&197"AddressRange is not a multiple of sizeof(T)");198return span<T>(Start.toPtr<T *>(), size() / sizeof(T));199}200201ExecutorAddr Start;202ExecutorAddr End;203};204205/// SPS serializatior for ExecutorAddr.206template <> class SPSSerializationTraits<SPSExecutorAddr, ExecutorAddr> {207public:208static size_t size(const ExecutorAddr &EA) {209return SPSArgList<uint64_t>::size(EA.getValue());210}211212static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddr &EA) {213return SPSArgList<uint64_t>::serialize(BOB, EA.getValue());214}215216static bool deserialize(SPSInputBuffer &BIB, ExecutorAddr &EA) {217uint64_t Tmp;218if (!SPSArgList<uint64_t>::deserialize(BIB, Tmp))219return false;220EA = ExecutorAddr(Tmp);221return true;222}223};224225using SPSExecutorAddrRange = SPSTuple<SPSExecutorAddr, SPSExecutorAddr>;226227/// Serialization traits for address ranges.228template <>229class SPSSerializationTraits<SPSExecutorAddrRange, ExecutorAddrRange> {230public:231static size_t size(const ExecutorAddrRange &Value) {232return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::size(Value.Start,233Value.End);234}235236static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddrRange &Value) {237return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::serialize(238BOB, Value.Start, Value.End);239}240241static bool deserialize(SPSInputBuffer &BIB, ExecutorAddrRange &Value) {242return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::deserialize(243BIB, Value.Start, Value.End);244}245};246247using SPSExecutorAddrRangeSequence = SPSSequence<SPSExecutorAddrRange>;248249} // End namespace __orc_rt250251namespace std {252253// Make ExecutorAddr hashable.254template <> struct hash<__orc_rt::ExecutorAddr> {255size_t operator()(const __orc_rt::ExecutorAddr &A) const {256return hash<uint64_t>()(A.getValue());257}258};259260} // namespace std261262#endif // ORC_RT_EXECUTOR_ADDRESS_H263264265