1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #ifndef BERBERIS_RUNTIME_PRIMITIVES_HOST_CODE_H_
17 #define BERBERIS_RUNTIME_PRIMITIVES_HOST_CODE_H_
18
19 #include <cstdint>
20
21 #include "berberis/base/bit_util.h"
22 #include "berberis/base/checks.h"
23
24 namespace berberis {
25
26 // Pointer to host executable machine code.
27 using HostCode = const void*;
28
29 // Type used in translation cache and for host_entries
30 #if defined(__x86_64__)
31 using HostCodeAddr = uint32_t;
32
AsHostCodeAddr(HostCode host_code)33 inline HostCodeAddr AsHostCodeAddr(HostCode host_code) {
34 CHECK(IsInRange<HostCodeAddr>(bit_cast<uintptr_t>(host_code)));
35 return static_cast<HostCodeAddr>(bit_cast<uintptr_t>(host_code));
36 }
37
AsHostCode(HostCodeAddr host_code_addr)38 inline HostCode AsHostCode(HostCodeAddr host_code_addr) {
39 return bit_cast<HostCode>(uintptr_t{host_code_addr});
40 }
41 #else
42 // TODO(b/363611588): use uint32_t for other 64bit backends (arm64/riscv64)
43 using HostCodeAddr = uintptr_t;
44
AsHostCodeAddr(HostCode host_code)45 inline HostCodeAddr AsHostCodeAddr(HostCode host_code) {
46 return bit_cast<HostCodeAddr>(host_code);
47 }
48
AsHostCode(HostCodeAddr host_code_addr)49 inline HostCode AsHostCode(HostCodeAddr host_code_addr) {
50 return bit_cast<HostCode>(host_code_addr);
51 }
52 #endif // defined(__x86_64__)
53
54 constexpr HostCodeAddr kNullHostCodeAddr = 0;
55
56 template <typename T>
AsHostCode(T ptr)57 inline HostCode AsHostCode(T ptr) {
58 return reinterpret_cast<HostCode>(ptr);
59 }
60
61 template <typename T>
AsFuncPtr(HostCode ptr)62 inline T AsFuncPtr(HostCode ptr) {
63 return reinterpret_cast<T>(const_cast<void*>(ptr));
64 }
65
66 // Note: ideally we would like the class to be a local class in the AsFuncPtr function below, but
67 // C++ doesn't allow that: local classes are not supposed to have template members.
68 class AsFuncPtrAdaptor;
69 AsFuncPtrAdaptor AsFuncPtr(HostCode ptr);
70 class [[nodiscard]] AsFuncPtrAdaptor {
71 // Note: we need this helper to describe the operator on the next line. Otherwise the C++ syntax
72 // parser becomes very confused. It has to come before the operator to help the parser, though.
73 template <typename Result, typename... Args>
74 using MakeFunctionType = Result (*)(Args...);
75
76 public:
77 template <typename Result, typename... Args>
78 operator MakeFunctionType<Result, Args...>() {
79 return reinterpret_cast<MakeFunctionType<Result, Args...>>(ptr_);
80 }
81
82 private:
83 AsFuncPtrAdaptor() = delete;
84 AsFuncPtrAdaptor(const AsFuncPtrAdaptor&) = delete;
85 AsFuncPtrAdaptor(AsFuncPtrAdaptor&&) = delete;
86 AsFuncPtrAdaptor& operator=(const AsFuncPtrAdaptor&) = delete;
87 AsFuncPtrAdaptor& operator=(AsFuncPtrAdaptor&&) = delete;
AsFuncPtrAdaptor(HostCode ptr)88 constexpr explicit AsFuncPtrAdaptor(HostCode ptr) noexcept : ptr_(const_cast<void*>(ptr)) {}
89 friend AsFuncPtrAdaptor AsFuncPtr(HostCode);
90 void* ptr_;
91 };
92
93 // The result of this function is assumed to be assigned to a non-auto variable type, which will
94 // involve the conversion operator of AsFuncPtrAdaptor.
AsFuncPtr(HostCode ptr)95 inline AsFuncPtrAdaptor AsFuncPtr(HostCode ptr) {
96 return AsFuncPtrAdaptor{ptr};
97 }
98
99 struct HostCodePiece {
100 HostCodeAddr code;
101 uint32_t size;
102 };
103
104 } // namespace berberis
105
106 #endif // BERBERIS_RUNTIME_PRIMITIVES_HOST_CODE_H_
107