1/*
2 * Copyright (c) 2023 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 ECMASCRIPT_COMPILER_MCR_GATE_META_DATA_H
17#define ECMASCRIPT_COMPILER_MCR_GATE_META_DATA_H
18
19#include <string>
20
21#include "ecmascript/compiler/bytecodes.h"
22#include "ecmascript/compiler/type.h"
23#include "ecmascript/mem/chunk.h"
24#include "ecmascript/mem/chunk_containers.h"
25
26#include "ecmascript/elements.h"
27#include "ecmascript/pgo_profiler/types/pgo_profiler_type.h"
28#include "libpandabase/macros.h"
29
30#include "ecmascript/compiler/share_gate_meta_data.h"
31
32namespace panda::ecmascript::kungfu {
33
34#define TYPED_BIN_OP_LIST(V)    \
35    V(TYPED_ADD)                \
36    V(TYPED_SUB)                \
37    V(TYPED_MUL)                \
38    V(TYPED_DIV)                \
39    V(TYPED_MOD)                \
40    V(TYPED_LESS)               \
41    V(TYPED_LESSEQ)             \
42    V(TYPED_GREATER)            \
43    V(TYPED_GREATEREQ)          \
44    V(TYPED_EQ)                 \
45    V(TYPED_NOTEQ)              \
46    V(TYPED_STRICTEQ)           \
47    V(TYPED_STRICTNOTEQ)        \
48    V(TYPED_SHL)                \
49    V(TYPED_SHR)                \
50    V(TYPED_ASHR)               \
51    V(TYPED_AND)                \
52    V(TYPED_OR)                 \
53    V(TYPED_XOR)                \
54    V(TYPED_EXP)
55
56#define TYPED_UN_OP_LIST(V) \
57    V(TYPED_NEG)            \
58    V(TYPED_NOT)            \
59    V(TYPED_INC)            \
60    V(TYPED_DEC)            \
61    V(TYPED_ISFALSE)        \
62    V(TYPED_ISTRUE)
63
64#define TYPED_JUMP_OP_LIST(V)   \
65    V(TYPED_JEQZ)               \
66    V(TYPED_JNEZ)
67
68#define TYPED_LOAD_OP_LIST(V)           \
69    V(ARRAY_LOAD_INT_ELEMENT)           \
70    V(ARRAY_LOAD_DOUBLE_ELEMENT)        \
71    V(ARRAY_LOAD_OBJECT_ELEMENT)        \
72    V(ARRAY_LOAD_TAGGED_ELEMENT)        \
73    V(ARRAY_LOAD_HOLE_TAGGED_ELEMENT)   \
74    V(ARRAY_LOAD_HOLE_INT_ELEMENT)      \
75    V(ARRAY_LOAD_HOLE_DOUBLE_ELEMENT)   \
76    V(INT8ARRAY_LOAD_ELEMENT)           \
77    V(UINT8ARRAY_LOAD_ELEMENT)          \
78    V(UINT8CLAMPEDARRAY_LOAD_ELEMENT)   \
79    V(INT16ARRAY_LOAD_ELEMENT)          \
80    V(UINT16ARRAY_LOAD_ELEMENT)         \
81    V(INT32ARRAY_LOAD_ELEMENT)          \
82    V(UINT32ARRAY_LOAD_ELEMENT)         \
83    V(FLOAT32ARRAY_LOAD_ELEMENT)        \
84    V(FLOAT64ARRAY_LOAD_ELEMENT)        \
85    V(STRING_LOAD_ELEMENT)
86
87#define TYPED_STORE_OP_LIST(V)          \
88    V(ARRAY_STORE_ELEMENT)              \
89    V(ARRAY_STORE_INT_ELEMENT)          \
90    V(ARRAY_STORE_DOUBLE_ELEMENT)       \
91    V(INT8ARRAY_STORE_ELEMENT)          \
92    V(UINT8ARRAY_STORE_ELEMENT)         \
93    V(UINT8CLAMPEDARRAY_STORE_ELEMENT)  \
94    V(INT16ARRAY_STORE_ELEMENT)         \
95    V(UINT16ARRAY_STORE_ELEMENT)        \
96    V(INT32ARRAY_STORE_ELEMENT)         \
97    V(UINT32ARRAY_STORE_ELEMENT)        \
98    V(FLOAT32ARRAY_STORE_ELEMENT)       \
99    V(FLOAT64ARRAY_STORE_ELEMENT)
100
101#define TYPED_CALL_TARGET_CHECK_OP_LIST(V)  \
102    V(JSCALL)                               \
103    V(JSCALL_FAST)                          \
104    V(JSCALLTHIS)                           \
105    V(JSCALLTHIS_FAST)                      \
106    V(JSCALLTHIS_NOGC)                      \
107    V(JSCALLTHIS_FAST_NOGC)                 \
108    V(JS_NEWOBJRANGE)
109
110enum class TypedBinOp : uint8_t {
111#define DECLARE_TYPED_BIN_OP(OP) OP,
112    TYPED_BIN_OP_LIST(DECLARE_TYPED_BIN_OP)
113#undef DECLARE_TYPED_BIN_OP
114};
115
116enum class TypedUnOp : uint8_t {
117#define DECLARE_TYPED_UN_OP(OP) OP,
118    TYPED_UN_OP_LIST(DECLARE_TYPED_UN_OP)
119#undef DECLARE_TYPED_UN_OP
120};
121
122enum class TypedJumpOp : uint8_t {
123#define DECLARE_TYPED_JUMP_OP(OP) OP,
124    TYPED_JUMP_OP_LIST(DECLARE_TYPED_JUMP_OP)
125#undef DECLARE_TYPED_JUMP_OP
126};
127
128enum class TypedLoadOp : uint8_t {
129#define DECLARE_TYPED_LOAD_OP(OP) OP,
130    TYPED_LOAD_OP_LIST(DECLARE_TYPED_LOAD_OP)
131#undef DECLARE_TYPED_LOAD_OP
132    TYPED_ARRAY_FIRST = INT8ARRAY_LOAD_ELEMENT,
133    TYPED_ARRAY_LAST = FLOAT64ARRAY_LOAD_ELEMENT,
134};
135
136enum class TypedStoreOp : uint8_t {
137#define DECLARE_TYPED_STORE_OP(OP) OP,
138    TYPED_STORE_OP_LIST(DECLARE_TYPED_STORE_OP)
139#undef DECLARE_TYPED_STORE_OP
140    TYPED_ARRAY_FIRST = INT8ARRAY_STORE_ELEMENT,
141    TYPED_ARRAY_LAST = FLOAT64ARRAY_STORE_ELEMENT,
142};
143
144enum class TypedCallTargetCheckOp : uint8_t {
145#define DECLARE_TYPED_CALL_TARGET_CHECK_OP(OP) OP,
146    TYPED_CALL_TARGET_CHECK_OP_LIST(DECLARE_TYPED_CALL_TARGET_CHECK_OP)
147#undef DECLARE_TYPED_CALL_TARGET_CHECK_OP
148};
149
150enum class BranchKind : uint8_t {
151    NORMAL_BRANCH = 0,
152    TRUE_BRANCH,
153    FALSE_BRANCH,
154    STRONG_TRUE_BRANCH,
155    STRONG_FALSE_BRANCH,
156};
157
158enum class TypedOpKind : uint8_t {
159    TYPED_BIN_OP,
160    TYPED_CALL_TARGET_CHECK_OP,
161    TYPED_UN_OP,
162    TYPED_JUMP_OP,
163    TYPED_STORE_OP,
164    TYPED_LOAD_OP,
165};
166
167enum class MemoryType : uint8_t {
168    ELEMENT_TYPE = 0,
169};
170
171class TypedCallMetaData : public OneParameterMetaData {
172public:
173    TypedCallMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn,
174        uint16_t dependsIn, uint32_t valuesIn, uint64_t value, bool noGC)
175        : OneParameterMetaData(opcode, flags, statesIn, dependsIn, valuesIn, value),
176        noGC_(noGC)
177    {
178        SetKind(GateMetaData::Kind::TYPED_CALL);
179    }
180
181    bool equal(const GateMetaData &other) const override
182    {
183        if (!OneParameterMetaData::equal(other)) {
184            return false;
185        }
186        auto cast_other = static_cast<const TypedCallMetaData *>(&other);
187        if (noGC_ == cast_other->noGC_) {
188            return true;
189        }
190        return false;
191    }
192
193    static const TypedCallMetaData* Cast(const GateMetaData* meta)
194    {
195        meta->AssertKind(GateMetaData::Kind::TYPED_CALL);
196        return static_cast<const TypedCallMetaData*>(meta);
197    }
198
199    bool IsNoGC() const
200    {
201        return noGC_;
202    }
203private:
204    bool noGC_;
205};
206
207class NewConstructMetaData : public OneParameterMetaData {
208public:
209    static constexpr int NEED_PUSH_ARGV_BIT_SIZE = 1;
210    NewConstructMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn,
211        uint16_t dependsIn, uint32_t valuesIn, uint64_t value, bool needPushArgv)
212        : OneParameterMetaData(opcode, flags, statesIn, dependsIn, valuesIn, value)
213    {
214        bitField_ = NeedPushArgvBit::Encode(needPushArgv);
215    }
216
217    static const NewConstructMetaData* Cast(const GateMetaData* meta)
218    {
219        meta->AssertKind(GateMetaData::Kind::CALL_NEW);
220        return static_cast<const NewConstructMetaData*>(meta);
221    }
222
223    bool NeedPushArgv() const
224    {
225        return NeedPushArgvBit::Get(bitField_);
226    }
227
228    uint64_t GetValue() const
229    {
230        return bitField_;
231    }
232
233private:
234    using NeedPushArgvBit = panda::BitField<bool, 0, NEED_PUSH_ARGV_BIT_SIZE>;
235
236    uint64_t bitField_;
237};
238
239class TypedUnaryAccessor {
240public:
241    // type bits shift
242    static constexpr int OPRAND_TYPE_BITS = 32;
243    explicit TypedUnaryAccessor(uint64_t value) : bitField_(value) {}
244
245    ParamType GetParamType() const
246    {
247        return ParamType(TypedValueBits::Get(bitField_));
248    }
249
250    TypedUnOp GetTypedUnOp() const
251    {
252        return TypedUnOpBits::Get(bitField_);
253    }
254
255    static uint64_t ToValue(ParamType paramType, TypedUnOp unaryOp)
256    {
257        return TypedValueBits::Encode(paramType.Value()) | TypedUnOpBits::Encode(unaryOp);
258    }
259
260private:
261    using TypedValueBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
262    using TypedUnOpBits = TypedValueBits::NextField<TypedUnOp, OPRAND_TYPE_BITS>;
263
264    uint64_t bitField_;
265};
266
267class TypedBinaryAccessor {
268public:
269    // type bits shift
270    static constexpr int OPRAND_TYPE_BITS = 32;
271    explicit TypedBinaryAccessor(uint64_t value) : bitField_(value) {}
272
273    ParamType GetParamType() const
274    {
275        return ParamType(TypedValueBits::Get(bitField_));
276    }
277
278    TypedBinOp GetTypedBinOp() const
279    {
280        return TypedBinOpBits::Get(bitField_);
281    }
282
283    static uint64_t ToValue(ParamType operandType, TypedBinOp binOp)
284    {
285        return TypedValueBits::Encode(operandType.Value()) | TypedBinOpBits::Encode(binOp);
286    }
287
288private:
289    using TypedValueBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
290    using TypedBinOpBits = TypedValueBits::NextField<TypedBinOp, OPRAND_TYPE_BITS>;
291
292    uint64_t bitField_;
293};
294
295class TypedCallTargetCheckAccessor {
296public:
297    // type bits shift
298    static constexpr int CALLTARGETCHECK_OP_BITS = 32;
299    explicit TypedCallTargetCheckAccessor(uint64_t value) : bitField_(value) {}
300
301    TypedCallTargetCheckOp GetCallTargetCheckOp() const
302    {
303        return CallTargetCheckOpBits::Get(bitField_);
304    }
305
306    static uint64_t ToValue(TypedCallTargetCheckOp op)
307    {
308        return CallTargetCheckOpBits::Encode(op);
309    }
310
311private:
312    using CallTargetCheckOpBits = panda::BitField<TypedCallTargetCheckOp, 0, CALLTARGETCHECK_OP_BITS>;
313
314    uint64_t bitField_;
315};
316
317class BranchAccessor {
318public:
319    // type bits shift
320    static constexpr int OPRAND_TYPE_BITS = 32;
321    explicit BranchAccessor(uint64_t value) : bitField_(value) {}
322
323    int32_t GetTrueWeight() const
324    {
325        return TrueWeightBits::Get(bitField_);
326    }
327
328    int32_t GetFalseWeight() const
329    {
330        return FalseWeightBits::Get(bitField_);
331    }
332
333    static uint64_t ToValue(uint32_t trueWeight, uint32_t falseWeight)
334    {
335        return TrueWeightBits::Encode(trueWeight)
336            | FalseWeightBits::Encode(falseWeight);
337    }
338private:
339    using TrueWeightBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
340    using FalseWeightBits = TrueWeightBits::NextField<uint32_t, OPRAND_TYPE_BITS>;
341
342    uint64_t bitField_;
343};
344
345class MemoryAttribute {
346public:
347    MemoryAttribute() = default;
348    ~MemoryAttribute() = default;
349    explicit MemoryAttribute(uint32_t v) : value_(v) {}
350
351    enum Order {
352        NOT_ATOMIC = 0,
353        MEMORY_ORDER_RELEASE
354    };
355
356    enum Barrier {
357        NEED_BARRIER = 0,
358        NO_BARRIER,
359        UNKNOWN_BARRIER
360    };
361
362    enum ShareFlag {
363        UNKNOWN = 0,
364        NON_SHARE,
365        SHARED
366    };
367
368    static MemoryAttribute Default()
369    {
370        return Create(NOT_ATOMIC);
371    }
372
373    static MemoryAttribute NeedBarrier()
374    {
375        return Create(NOT_ATOMIC, NEED_BARRIER);
376    }
377
378    static MemoryAttribute UnknownBarrier()
379    {
380        return Create(NOT_ATOMIC, UNKNOWN_BARRIER);
381    }
382
383    static MemoryAttribute DefaultWithShareBarrier()
384    {
385        return Create(NOT_ATOMIC, UNKNOWN_BARRIER, SHARED);
386    }
387
388    static MemoryAttribute NeedNotShareBarrier()
389    {
390        return Create(NOT_ATOMIC, NEED_BARRIER, NON_SHARE);
391    }
392
393    static MemoryAttribute NeedBarrierAndAtomic()
394    {
395        return Create(MEMORY_ORDER_RELEASE, NEED_BARRIER);
396    }
397
398    static MemoryAttribute NoBarrier()
399    {
400        return Create(NOT_ATOMIC, NO_BARRIER);
401    }
402
403    void SetBarrier(Barrier barrier)
404    {
405        BarrierField::Set<uint32_t>(barrier, &value_);
406    }
407
408    Barrier GetBarrier() const
409    {
410        return BarrierField::Get(value_);
411    }
412
413    void SetShare(ShareFlag share)
414    {
415        ShareField::Set<uint32_t>(share, &value_);
416    }
417
418    ShareFlag GetShare() const
419    {
420        return ShareField::Get(value_);
421    }
422
423    void SetOrder(Order order)
424    {
425        OrderField::Set<uint32_t>(order, &value_);
426    }
427
428    Order GetOrder() const
429    {
430        return OrderField::Get(value_);
431    }
432
433    uint32_t Value() const
434    {
435        return value_;
436    }
437
438private:
439    static MemoryAttribute Create(Order order, Barrier barrier = UNKNOWN_BARRIER, ShareFlag share = UNKNOWN)
440    {
441        uint32_t value = OrderField::Encode(order) | BarrierField::Encode(barrier) | ShareField::Encode(share);
442        return MemoryAttribute(value);
443    }
444
445    static constexpr uint32_t ORDER_BITS = 8;
446    static constexpr uint32_t BARRIER_BITS = 8;
447    static constexpr uint32_t SHARE_BITS = 8;
448    using OrderField = panda::BitField<Order, 0, ORDER_BITS>;
449    using BarrierField = OrderField::NextField<Barrier, BARRIER_BITS>;
450    using ShareField = BarrierField::NextField<ShareFlag, SHARE_BITS>;
451
452    uint32_t value_;
453};
454
455class LoadStoreAccessor {
456public:
457    static constexpr int MEMORY_ORDER_BITS = 32;
458    explicit LoadStoreAccessor(uint64_t value) : bitField_(value) {}
459
460    MemoryAttribute GetMemoryAttribute() const
461    {
462        return MemoryAttribute(MemoryAttributeBits::Get(bitField_));
463    }
464
465    static uint64_t ToValue(MemoryAttribute mAttr)
466    {
467        return MemoryAttributeBits::Encode(mAttr.Value());
468    }
469private:
470    using MemoryAttributeBits = panda::BitField<uint32_t, 0, MEMORY_ORDER_BITS>;
471
472    uint64_t bitField_;
473};
474
475class LoadStoreConstOffsetAccessor {
476public:
477    static constexpr int OPRAND_OFFSET_BITS = 32;
478    static constexpr int MEMORY_ATTRIBUTE_BITS = 32;
479    explicit LoadStoreConstOffsetAccessor(uint64_t value) : bitField_(value) {}
480
481    MemoryAttribute GetMemoryAttribute() const
482    {
483        return MemoryAttribute(MemoryAttributeBits::Get(bitField_));
484    }
485
486    size_t GetOffset() const
487    {
488        return static_cast<size_t>(OprandOffsetBits::Get(bitField_));
489    }
490
491    static uint64_t ToValue(size_t offset, MemoryAttribute mAttr)
492    {
493        return OprandOffsetBits::Encode(static_cast<uint32_t>(offset)) |
494               MemoryAttributeBits::Encode(mAttr.Value());
495    }
496private:
497    using OprandOffsetBits = panda::BitField<uint32_t, 0, OPRAND_OFFSET_BITS>;
498    using MemoryAttributeBits = OprandOffsetBits::NextField<uint32_t, MEMORY_ATTRIBUTE_BITS>;
499
500    uint64_t bitField_;
501};
502
503class TypedJumpAccessor {
504public:
505    // type bits shift
506    static constexpr int OPRAND_TYPE_BITS = 32;
507    static constexpr int JUMP_OP_BITS = 8;
508    explicit TypedJumpAccessor(uint64_t value) : bitField_(value) {}
509
510    ParamType GetParamType() const
511    {
512        return ParamType(TypedValueBits::Get(bitField_));
513    }
514
515    TypedJumpOp GetTypedJumpOp() const
516    {
517        return TypedJumpOpBits::Get(bitField_);
518    }
519
520    uint32_t GetTrueWeight() const
521    {
522        return TrueWeightBits::Get(bitField_);
523    }
524
525    uint32_t GetFalseWeight() const
526    {
527        return FalseWeightBits::Get(bitField_);
528    }
529
530    static uint64_t ToValue(ParamType paramType, TypedJumpOp jumpOp, uint32_t weight)
531    {
532        return TypedValueBits::Encode(paramType.Value())
533            | TypedJumpOpBits::Encode(jumpOp)
534            | WeightBits::Encode(weight);
535    }
536
537private:
538    using TypedValueBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
539    using TypedJumpOpBits = TypedValueBits::NextField<TypedJumpOp, JUMP_OP_BITS>;
540    using WeightBits = TypedJumpOpBits::NextField<uint32_t, PGOSampleType::WEIGHT_BITS + PGOSampleType::WEIGHT_BITS>;
541    using FalseWeightBits = TypedJumpOpBits::NextField<uint32_t, PGOSampleType::WEIGHT_BITS>;
542    using TrueWeightBits = FalseWeightBits::NextField<uint32_t, PGOSampleType::WEIGHT_BITS>;
543
544    uint64_t bitField_;
545};
546
547}
548
549#endif  // ECMASCRIPT_COMPILER_MCR_GATE_META_DATA_H
550