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 namespace berberis {
22 
23 // Pointer to host executable machine code.
24 using HostCode = const void*;
25 
26 template <typename T>
AsHostCode(T ptr)27 inline HostCode AsHostCode(T ptr) {
28   return reinterpret_cast<HostCode>(ptr);
29 }
30 
31 template <typename T>
AsFuncPtr(HostCode ptr)32 inline T AsFuncPtr(HostCode ptr) {
33   return reinterpret_cast<T>(const_cast<void*>(ptr));
34 }
35 
36 // Note: ideally we would like the class to be a local class in the AsFuncPtr function below, but
37 // C++ doesn't allow that: local classes are not supposed to have template members.
38 class AsFuncPtrAdaptor;
39 AsFuncPtrAdaptor AsFuncPtr(HostCode ptr);
40 class [[nodiscard]] AsFuncPtrAdaptor {
41   // Note: we need this helper to describe the operator on the next line. Otherwise the C++ syntax
42   // parser becomes very confused. It has to come before the operator to help the parser, though.
43   template <typename Result, typename... Args>
44   using MakeFunctionType = Result (*)(Args...);
45 
46  public:
47   template <typename Result, typename... Args>
48   operator MakeFunctionType<Result, Args...>() {
49     return reinterpret_cast<MakeFunctionType<Result, Args...>>(ptr_);
50   }
51 
52  private:
53   AsFuncPtrAdaptor() = delete;
54   AsFuncPtrAdaptor(const AsFuncPtrAdaptor&) = delete;
55   AsFuncPtrAdaptor(AsFuncPtrAdaptor&&) = delete;
56   AsFuncPtrAdaptor& operator=(const AsFuncPtrAdaptor&) = delete;
57   AsFuncPtrAdaptor& operator=(AsFuncPtrAdaptor&&) = delete;
AsFuncPtrAdaptor(HostCode ptr)58   constexpr explicit AsFuncPtrAdaptor(HostCode ptr) noexcept : ptr_(const_cast<void*>(ptr)) {}
59   friend AsFuncPtrAdaptor AsFuncPtr(HostCode);
60   void* ptr_;
61 };
62 
63 // The result of this function is assumed to be assigned to a non-auto variable type, which will
64 // involve the conversion operator of AsFuncPtrAdaptor.
AsFuncPtr(HostCode ptr)65 inline AsFuncPtrAdaptor AsFuncPtr(HostCode ptr) {
66   return AsFuncPtrAdaptor{ptr};
67 }
68 
69 struct HostCodePiece {
70   HostCode code;
71   uint32_t size;
72 };
73 
74 }  // namespace berberis
75 
76 #endif  // BERBERIS_RUNTIME_PRIMITIVES_HOST_CODE_H_
77