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 
17 #ifndef BERBERIS_GUEST_ABI_GUEST_FUNCTION_WRAPPER_SIGNATURE_H_
18 #define BERBERIS_GUEST_ABI_GUEST_FUNCTION_WRAPPER_SIGNATURE_H_
19 
20 #include <cstdint>
21 #include <type_traits>
22 
23 namespace berberis {
24 
25 // Signature string:
26 //   "<return-type-char><param-type-char><param-type-char>"
27 //
28 // Supported types:
29 //   'v': void (as return type)
30 //   'z': unsigned integer and enum types == 8bit (jboolean equivalent)
31 //   'b': signed integer and enum types == 8bit (jbyte equivalent)
32 //   's': signed integer and enum types == 16bit (jshort equivalent)
33 //   'c': unsigned integer types == 16bit (jchar equivalent)
34 //   'i': integer and enum types == 32bit (jint equivalent)
35 //   'l': integer and enum types == 64bit (jfloat equivalent)
36 //   'p': pointers (to objects and functions but not to members)
37 //   'f': float (floating point 32 bits)
38 //   'd': double (floating point 64 bits)
39 //
40 // Signature char (template constant) for return type or parameter:
41 //   kGuestFunctionWrapperSignatureChar<Type>
42 //
43 // Signature (template constant) for function or function pointer:
44 //   kGuestFunctionWrapperSignature<int (int)>
45 
46 class kGuestFunctionWrapperSignatureCharHelper {
47  public:
48   template <typename Type, std::enable_if_t<std::is_same_v<Type, void>, int> = 0>
Value()49   static constexpr char Value() {
50     return 'v';
51   }
52 
53   template <typename Type,
54             std::enable_if_t<(std::is_integral_v<Type> ||
55                               std::is_enum_v<Type>)&&std::is_unsigned_v<Type> &&
56                                  sizeof(Type) == sizeof(uint8_t),
57                              int> = 0>
Value()58   static constexpr char Value() {
59     return 'z';
60   }
61 
62   template <
63       typename Type,
64       std::enable_if_t<(std::is_integral_v<Type> || std::is_enum_v<Type>)&&std::is_signed_v<Type> &&
65                            sizeof(Type) == sizeof(int8_t),
66                        int> = 0>
Value()67   static constexpr char Value() {
68     return 'b';
69   }
70 
71   template <
72       typename Type,
73       std::enable_if_t<(std::is_integral_v<Type> || std::is_enum_v<Type>)&&std::is_signed_v<Type> &&
74                            sizeof(Type) == sizeof(int16_t),
75                        int> = 0>
Value()76   static constexpr char Value() {
77     return 's';
78   }
79 
80   template <typename Type,
81             std::enable_if_t<std::is_integral_v<Type> && std::is_unsigned_v<Type> &&
82                                  sizeof(Type) == sizeof(uint16_t),
83                              int> = 0>
Value()84   static constexpr char Value() {
85     return 'c';
86   }
87 
88   template <typename Type,
89             std::enable_if_t<(std::is_integral_v<Type> || std::is_enum_v<Type>)&&sizeof(Type) ==
90                                  sizeof(int32_t),
91                              int> = 0>
Value()92   static constexpr char Value() {
93     return 'i';
94   }
95 
96   template <typename Type,
97             std::enable_if_t<(std::is_integral_v<Type> || std::is_enum_v<Type>)&&sizeof(Type) ==
98                                  sizeof(int64_t),
99                              int> = 0>
Value()100   static constexpr char Value() {
101     return 'l';
102   }
103 
104   template <typename Type, std::enable_if_t<std::is_pointer_v<Type>, int> = 0>
Value()105   static constexpr char Value() {
106     return 'p';
107   }
108 
109   template <
110       typename Type,
111       std::enable_if_t<std::is_same_v<Type, float> && sizeof(Type) == sizeof(int32_t), int> = 0>
Value()112   static constexpr char Value() {
113     return 'f';
114   }
115 
116   template <
117       typename Type,
118       std::enable_if_t<std::is_same_v<Type, double> && sizeof(Type) == sizeof(int64_t), int> = 0>
Value()119   static constexpr char Value() {
120     return 'd';
121   }
122 };
123 
124 template <typename Arg>
125 constexpr char kGuestFunctionWrapperSignatureChar =
126     kGuestFunctionWrapperSignatureCharHelper::Value<Arg>();
127 
128 template <typename Func>
129 class kGuestFunctionWrapperSignatureHelper;
130 
131 template <typename Result, typename... Args>
132 class kGuestFunctionWrapperSignatureHelper<Result (*)(Args...)> {
133  public:
134   constexpr static const char kValue[] = {kGuestFunctionWrapperSignatureChar<Result>,
135                                           kGuestFunctionWrapperSignatureChar<Args>...,
136                                           0};
137 };
138 
139 template <typename Func>
140 constexpr static const char (&kGuestFunctionWrapperSignature)[sizeof(
141     kGuestFunctionWrapperSignatureHelper<std::decay_t<Func>>::kValue)] =
142     kGuestFunctionWrapperSignatureHelper<std::decay_t<Func>>::kValue;
143 
144 }  // namespace berberis
145 
146 #endif  // BERBERIS_GUEST_ABI_GUEST_FUNCTION_WRAPPER_SIGNATURE_H_
147