• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #ifndef ECMASCRIPT_COMPILER_ASSEMBLER_H
16 #define ECMASCRIPT_COMPILER_ASSEMBLER_H
17 
18 #include "ecmascript/mem/dyn_chunk.h"
19 
20 namespace panda::ecmascript {
21 class GCStackMapRegisters {
22 public:
23 #if defined(PANDA_TARGET_AMD64)
24     static constexpr int SP = 7;
25     static constexpr int FP = 6;
26 #elif defined(PANDA_TARGET_ARM64)
27     static constexpr int SP = 31;  /* x31 */
28     static constexpr int FP = 29;  /* x29 */
29 #elif defined(PANDA_TARGET_ARM32)
30     static constexpr int SP = 13;
31     static constexpr int FP = 11;
32 #else
33     static constexpr int SP = -1;
34     static constexpr int FP = -1;
35 #endif
36 };
37 
38 enum Distance {
39     Near,
40     Far
41 };
42 
43 // When run from cpp to assembly code, there are some insts before the assembly frame is ready.
44 // When return from assembly code to cpp, there are some insts after the assembly frame is broken.
45 // And here are the numbers of insts. Only AsmInterpreterEntryFrame is dealt here, and there is no need
46 // for OptimizedEntryFrame because insts for OptimizedEntryFrame are negligible.
47 enum FrameCompletionPos : uint64_t {
48     // X64
49     X64CppToAsmInterp = 28,
50     X64AsmInterpToCpp = 9,
51     X64EntryFrameDuration = 70,
52     // ARM64
53     ARM64CppToAsmInterp = 56,
54     ARM64AsmInterpToCpp = 40,
55     ARM64EntryFrameDuration = 116,
56 };
57 
58 class Label {
59 public:
IsBound()60     bool IsBound() const
61     {
62         return pos_ > 0;
63     }
64 
IsLinked()65     bool IsLinked() const
66     {
67         return pos_ < 0;
68     }
69 
IsLinkedNear()70     bool IsLinkedNear() const
71     {
72         return nearPos_ > 0;
73     }
74 
GetPos()75     uint32_t GetPos() const
76     {
77         return static_cast<uint32_t>(pos_ - 1);
78     }
79 
GetLinkedPos()80     uint32_t GetLinkedPos() const
81     {
82         ASSERT(!IsBound());
83         return static_cast<uint32_t>(-pos_ - 1);
84     }
85 
BindTo(int32_t pos)86     void BindTo(int32_t pos)
87     {
88         // +1 skip offset 0
89         pos_ = pos + 1;
90     }
91 
LinkTo(int32_t pos)92     void LinkTo(int32_t pos)
93     {
94         // +1 skip offset 0
95         pos_ = - (pos + 1);
96     }
97 
UnlinkNearPos()98     void UnlinkNearPos()
99     {
100         nearPos_ = 0;
101     }
102 
LinkNearPos(uint32_t pos)103     void LinkNearPos(uint32_t pos)
104     {
105         // +1 skip offset 0
106         nearPos_ = pos + 1;
107     }
108 
GetLinkedNearPos()109     uint32_t GetLinkedNearPos() const
110     {
111         ASSERT(!IsBound());
112         return static_cast<uint32_t>(nearPos_ - 1);
113     }
114 
115 private:
116     int32_t pos_ = 0;
117     uint32_t nearPos_ = 0;
118 };
119 
120 class Assembler {
121 public:
Assembler(Chunk * chunk)122     explicit Assembler(Chunk *chunk)
123         : buffer_(chunk) {}
124     ~Assembler() = default;
125 
EmitU8(uint8_t v)126     void EmitU8(uint8_t v)
127     {
128         buffer_.EmitChar(v);
129     }
130 
EmitI8(int8_t v)131     void EmitI8(int8_t v)
132     {
133         buffer_.EmitChar(static_cast<uint8_t>(v));
134     }
135 
EmitU16(uint16_t v)136     void EmitU16(uint16_t v)
137     {
138         buffer_.EmitU16(v);
139     }
140 
EmitU32(uint32_t v)141     void EmitU32(uint32_t v)
142     {
143         buffer_.EmitU32(v);
144     }
145 
EmitI32(int32_t v)146     void EmitI32(int32_t v)
147     {
148         buffer_.EmitU32(static_cast<uint32_t>(v));
149     }
150 
EmitU64(uint64_t v)151     void EmitU64(uint64_t v)
152     {
153         buffer_.EmitU64(v);
154     }
155 
PutI8(size_t offset,int8_t data)156     void PutI8(size_t offset, int8_t data)
157     {
158         buffer_.PutU8(offset, static_cast<int8_t>(data));
159     }
160 
PutI32(size_t offset,int32_t data)161     void PutI32(size_t offset, int32_t data)
162     {
163         buffer_.PutU32(offset, static_cast<int32_t>(data));
164     }
165 
GetU32(size_t offset)166     uint32_t GetU32(size_t offset) const
167     {
168         return buffer_.GetU32(offset);
169     }
170 
GetI8(size_t offset)171     int8_t GetI8(size_t offset) const
172     {
173         return static_cast<int8_t>(buffer_.GetU8(offset));
174     }
175 
GetU8(size_t offset)176     uint8_t GetU8(size_t offset) const
177     {
178         return buffer_.GetU8(offset);
179     }
180 
GetCurrentPosition()181     size_t GetCurrentPosition() const
182     {
183         return buffer_.GetSize();
184     }
185 
GetBegin()186     uint8_t *GetBegin() const
187     {
188         return buffer_.GetBegin();
189     }
190 
InRangeN(int32_t x,uint32_t n)191     static bool InRangeN(int32_t x, uint32_t n)
192     {
193         int32_t limit = 1 << (n - 1);
194         return (x >= -limit) && (x < limit);
195     }
196 
InRange8(int32_t x)197     static bool InRange8(int32_t x)
198     {
199         // 8: range8
200         return InRangeN(x, 8);
201     }
202 
GetFrameCompletionPos(uint64_t & headerSize,uint64_t & tailSize,uint64_t & entryDuration)203     static void GetFrameCompletionPos(uint64_t &headerSize, uint64_t &tailSize, uint64_t &entryDuration)
204     {
205 #if defined(PANDA_TARGET_AMD64)
206         headerSize = FrameCompletionPos::X64CppToAsmInterp;
207         tailSize = FrameCompletionPos::X64AsmInterpToCpp;
208         entryDuration = FrameCompletionPos::X64EntryFrameDuration;
209 #elif defined(PANDA_TARGET_ARM64)
210         headerSize = FrameCompletionPos::ARM64CppToAsmInterp;
211         tailSize = FrameCompletionPos::ARM64AsmInterpToCpp;
212         entryDuration = FrameCompletionPos::ARM64EntryFrameDuration;
213 #else
214         headerSize = 0;
215         tailSize = 0;
216         entryDuration = 0;
217         LOG_ECMA(FATAL) << "Assembler does not currently support other platforms, please run on x64 and arm64";
218 #endif
219     }
220 private:
221     DynChunk buffer_;
222 };
223 }  // panda::ecmascript
224 #endif  // ECMASCRIPT_COMPILER_ASSEMBLER_H
225