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 LIBPANDAFILE_BYTECODE_INSTRUCTION_INL_H_
17 #define LIBPANDAFILE_BYTECODE_INSTRUCTION_INL_H_
18 
19 #include "bytecode_instruction.h"
20 #include "macros.h"
21 
22 namespace ark {
23 
24 template <const BytecodeInstMode MODE>
25 template <class R, class S>
ReadHelper(size_t byteoffset, size_t bytecount, size_t offset, size_t width) const26 inline auto BytecodeInst<MODE>::ReadHelper(size_t byteoffset, size_t bytecount, size_t offset, size_t width) const
27 {
28     constexpr size_t BYTE_WIDTH = 8;
29 
30     S v = 0;
31     for (size_t i = 0; i < bytecount; i++) {
32         S mask = static_cast<S>(ReadByte(byteoffset + i)) << (i * BYTE_WIDTH);
33         v |= mask;
34     }
35 
36     v >>= offset % BYTE_WIDTH;
37     size_t leftShift = sizeof(R) * BYTE_WIDTH - width;
38 
39     // Do sign extension using arithmetic shift. It's implementation defined
40     // so we check such behavior using static assert
41     // NOLINTNEXTLINE(hicpp-signed-bitwise)
42     static_assert((-1 >> 1) == -1);
43 
44     // NOLINTNEXTLINE(hicpp-signed-bitwise)
45     return static_cast<R>(v << leftShift) >> leftShift;
46 }
47 
48 template <const BytecodeInstMode MODE>
49 template <size_t OFFSET, size_t WIDTH, bool IS_SIGNED>
Read() const50 inline auto BytecodeInst<MODE>::Read() const
51 {
52     constexpr size_t BYTE_WIDTH = 8;
53     constexpr size_t BYTE_OFFSET = OFFSET / BYTE_WIDTH;
54     constexpr size_t BYTE_OFFSET_END = (OFFSET + WIDTH + BYTE_WIDTH - 1) / BYTE_WIDTH;
55     constexpr size_t BYTE_COUNT = BYTE_OFFSET_END - BYTE_OFFSET;
56 
57     using StorageType = helpers::TypeHelperT<BYTE_COUNT * BYTE_WIDTH, false>;
58     using ReturnType = helpers::TypeHelperT<WIDTH, IS_SIGNED>;
59 
60     return ReadHelper<ReturnType, StorageType>(BYTE_OFFSET, BYTE_COUNT, OFFSET, WIDTH);
61 }
62 
63 template <const BytecodeInstMode MODE>
64 template <bool IS_SIGNED>
Read64(size_t offset, size_t width) const65 inline auto BytecodeInst<MODE>::Read64(size_t offset, size_t width) const
66 {
67     constexpr size_t BIT64 = 64;
68     constexpr size_t BYTE_WIDTH = 8;
69 
70     ASSERT((offset % BYTE_WIDTH) + width <= BIT64);
71 
72     size_t byteoffset = offset / BYTE_WIDTH;
73     size_t byteoffsetEnd = (offset + width + BYTE_WIDTH - 1) / BYTE_WIDTH;
74     size_t bytecount = byteoffsetEnd - byteoffset;
75 
76     using StorageType = helpers::TypeHelperT<BIT64, false>;
77     using ReturnType = helpers::TypeHelperT<BIT64, IS_SIGNED>;
78 
79     return ReadHelper<ReturnType, StorageType>(byteoffset, bytecount, offset, width);
80 }
81 
82 template <const BytecodeInstMode MODE>
83 template <typename EnumT>
GetSize() const84 inline size_t BytecodeInst<MODE>::GetSize() const
85 {
86     return Size(GetFormat<EnumT>());
87 }
88 
89 #include <bytecode_instruction-inl_gen.h>
90 
91 }  // namespace ark
92 
93 #endif  // LIBPANDAFILE_BYTECODE_INSTRUCTION_INL_H_
94