• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_RUNTIME_TESTS_INVOCATION_HELPER_H_
17 #define PANDA_RUNTIME_TESTS_INVOCATION_HELPER_H_
18 
19 #include <cstdint>
20 #include <type_traits>
21 
22 #include "bridge/bridge.h"
23 #include "include/managed_thread.h"
24 #include "arch/helpers.h"
25 #include "libpandafile/shorty_iterator.h"
26 
27 namespace ark::test {
28 
29 const void *GetInvokeHelperImpl();
30 
31 template <typename T>
GetInvokeHelper()32 auto GetInvokeHelper()
33 {
34     using Fn = T (*)(const uint8_t *, const uint8_t *, const uint8_t *, size_t, ark::ManagedThread *);
35     return reinterpret_cast<Fn>(const_cast<void *>(GetInvokeHelperImpl()));
36 }
37 
WriteArgImpl(arch::ArgWriter<RUNTIME_ARCH> *,size_t)38 inline void WriteArgImpl(arch::ArgWriter<RUNTIME_ARCH> * /* unused */, size_t /* unused */) {}
39 
40 template <typename T, typename... Args>
41 inline void WriteArgImpl(arch::ArgWriter<RUNTIME_ARCH> *writer, size_t nfloats, T arg, Args... args);
42 
43 template <typename... Args>
WriteArgImpl(arch::ArgWriter<RUNTIME_ARCH> * writer,size_t nfloats,float arg,Args...args)44 inline void WriteArgImpl(arch::ArgWriter<RUNTIME_ARCH> *writer, size_t nfloats, float arg, Args... args)
45 {
46     writer->Write(arg);
47     WriteArgImpl(writer, nfloats + 1, args...);
48 }
49 
50 template <typename T, typename... Args>
WriteArgImpl(arch::ArgWriter<RUNTIME_ARCH> * writer,size_t nfloats,T arg,Args...args)51 inline void WriteArgImpl(arch::ArgWriter<RUNTIME_ARCH> *writer, size_t nfloats, T arg, Args... args)
52 {
53     if (RUNTIME_ARCH == Arch::AARCH32 && std::is_same_v<double, T>) {
54         // JIT compiler doesn't pack floats according armhf ABI. So in the following case:
55         //
56         // void foo(f32 a0, f64 a1, f32 a2)
57         //
58         // Arguments will be passed in the following registers:
59         // a0 - s0
60         // a1 - d1
61         // a2 - s4
62         //
63         // But according to armhf ABI a0 and a2 should be packed into d0:
64         // a0 - s0
65         // a1 - d1
66         // a2 - s1
67         //
68         // So write additional float if necessary to prevent packing
69         // NOLINTNEXTLINE(hicpp-signed-bitwise)
70         if ((nfloats & 0x1) != 0) {
71             nfloats += 1;
72             writer->Write(0.0F);
73         }
74     }
75     writer->Write(arg);
76     WriteArgImpl(writer, nfloats, args...);
77 }
78 
79 template <class T, typename... Args>
WriteArg(arch::ArgWriter<RUNTIME_ARCH> * writer,T arg,Args...args)80 inline void WriteArg(arch::ArgWriter<RUNTIME_ARCH> *writer, T arg, Args... args)
81 {
82     WriteArgImpl(writer, 0, arg, args...);
83 }
84 
85 template <typename T>
InvokeEntryPoint(Method * method)86 inline T InvokeEntryPoint(Method *method)
87 {
88     PandaVector<uint8_t> gprData(arch::ExtArchTraits<RUNTIME_ARCH>::GP_ARG_NUM_BYTES);
89     Span<uint8_t> gprs(gprData.data(), gprData.size());
90     PandaVector<uint8_t> fprData(arch::ExtArchTraits<RUNTIME_ARCH>::FP_ARG_NUM_BYTES);
91     Span<uint8_t> fprs(fprData.data(), fprData.size());
92     PandaVector<uint8_t> stack;
93     arch::ArgWriter<RUNTIME_ARCH> writer(gprs, fprs, stack.data());
94     writer.Write(method);
95 
96     ManagedThread *thread = ManagedThread::GetCurrent();
97     return GetInvokeHelper<T>()(gprData.data(), fprData.data(), stack.data(), 0, thread);
98 }
99 
100 void CountMethodTypes(panda_file::ShortyIterator &it, arch::ArgCounter<RUNTIME_ARCH> counter);
101 
102 template <typename T, typename... Args>
InvokeEntryPoint(Method * method,Args...args)103 T InvokeEntryPoint(Method *method, Args... args)
104 {
105     arch::ArgCounter<RUNTIME_ARCH> counter;
106     counter.Count<Method *>();
107     if (!method->IsStatic()) {
108         counter.Count<ObjectHeader *>();
109     }
110     panda_file::ShortyIterator it(method->GetShorty());
111     ++it;  // skip return type
112     while (it != panda_file::ShortyIterator()) {
113         CountMethodTypes(it, counter);
114         ++it;
115     }
116 
117     PandaVector<uint8_t> gprData(arch::ExtArchTraits<RUNTIME_ARCH>::GP_ARG_NUM_BYTES);
118     Span<uint8_t> gprs(gprData.data(), gprData.size());
119     PandaVector<uint8_t> fprData(arch::ExtArchTraits<RUNTIME_ARCH>::FP_ARG_NUM_BYTES);
120     Span<uint8_t> fprs(fprData.data(), fprData.size());
121     PandaVector<uint8_t> stack(counter.GetStackSpaceSize());
122     arch::ArgWriter<RUNTIME_ARCH> writer(gprs, fprs, stack.data());
123     writer.Write(method);
124     WriteArg(&writer, args...);
125 
126     ManagedThread *thread = ManagedThread::GetCurrent();
127     return GetInvokeHelper<T>()(gprData.data(), fprData.data(), stack.data(), counter.GetStackSize(), thread);
128 }
129 
130 template <typename... Args>
InvokeDynEntryPoint(Method * method,uint32_t numArgs,Args...args)131 coretypes::TaggedValue InvokeDynEntryPoint(Method *method, uint32_t numArgs, Args... args)
132 {
133     arch::ArgCounter<RUNTIME_ARCH> counter;
134     counter.Count<Method *>();
135     counter.Count<uint32_t>();
136     for (uint32_t i = 0; i <= numArgs; ++i) {
137         counter.Count<coretypes::TaggedValue>();
138     }
139 
140     PandaVector<uint8_t> gprData(arch::ExtArchTraits<RUNTIME_ARCH>::GP_ARG_NUM_BYTES);
141     Span<uint8_t> gprs(gprData.data(), gprData.size());
142     PandaVector<uint8_t> fprData(arch::ExtArchTraits<RUNTIME_ARCH>::FP_ARG_NUM_BYTES);
143     Span<uint8_t> fprs(fprData.data(), fprData.size());
144     PandaVector<uint8_t> stack(counter.GetStackSpaceSize());
145     arch::ArgWriter<RUNTIME_ARCH> writer(gprs, fprs, stack.data());
146     writer.Write(method);
147     writer.Write(numArgs);
148     WriteArg(&writer, args...);
149 
150     ManagedThread *thread = ManagedThread::GetCurrent();
151     return GetInvokeHelper<coretypes::TaggedValue>()(gprData.data(), fprData.data(), stack.data(),
152                                                      counter.GetStackSize(), thread);
153 }
154 
155 }  // namespace ark::test
156 
157 #endif  // PANDA_RUNTIME_TESTS_INVOCATION_HELPER_H_
158