1/*
2 * Copyright (c) 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 ECMASCRIPT_COMPILER_BASELINE_BASELINE_COMPILER_H
17#define ECMASCRIPT_COMPILER_BASELINE_BASELINE_COMPILER_H
18
19#include <unordered_map>
20#include "ecmascript/ecma_vm.h"
21#include "ecmascript/mem/machine_code.h"
22#include "ecmascript/compiler/baseline/baseline_assembler.h"
23#include "ecmascript/compiler/ecma_opcode_des.h"
24#include "ecmascript/compiler/jit_compilation_env.h"
25
26namespace panda::ecmascript::kungfu {
27
28class BytecodeNativePcOffsetTable {
29public:
30    BytecodeNativePcOffsetTable() = default;
31    ~BytecodeNativePcOffsetTable() = default;
32
33    void AddPosition(uint64_t nativePc)
34    {
35        ASSERT(nativePc - prevNativePc < 256); // 256: the max number can be presented by uint8_t
36        auto nativePcDiff = static_cast<uint8_t>(nativePc - prevNativePc);
37        nativePcDiffInfo.emplace_back(static_cast<uint8_t>(nativePcDiff));
38        prevNativePc = nativePc;
39    }
40
41    uint8_t *GetData()
42    {
43        return nativePcDiffInfo.data();
44    }
45
46    size_t GetSize() const
47    {
48        return nativePcDiffInfo.size();
49    }
50
51    uint64_t GetPrevNativePc() const
52    {
53        return prevNativePc;
54    }
55
56private:
57    uint64_t prevNativePc = 0;
58    std::vector<uint8_t> nativePcDiffInfo;
59};
60
61class BaselineCompiler {
62public:
63    explicit BaselineCompiler(EcmaVM *inputVM, CompilationEnv *inputEnv)
64        : vm(inputVM), compilationEnv(inputEnv), baselineAssembler(vm->GetJSOptions().GetTargetTriple()) {}
65
66    ~BaselineCompiler()
67    {
68        for (auto elem : jumpMap) {
69            if (elem.second != nullptr) {
70                delete elem.second;
71                elem.second = nullptr;
72            }
73        }
74        jumpMap.clear();
75    }
76
77    void Compile(const JSPandaFile *jsPandaFile, const MethodLiteral *methodLiteral);
78
79    BaselineAssembler &GetBaselineAssembler()
80    {
81        return baselineAssembler;
82    }
83
84    bool CollectMemoryCodeInfos(MachineCodeDesc &codeDesc);
85
86    void SetPfHeaderAddr(const JSPandaFile *jsPandaFile);
87
88    void GetJumpToOffsets(const uint8_t *start, const uint8_t *end, std::unordered_set<size_t> &jumpToOffsets) const;
89private:
90    EcmaVM *vm = nullptr;
91    CompilationEnv *compilationEnv = nullptr;
92    BaselineAssembler baselineAssembler;
93    size_t bytecodeOffset = 0;
94    std::unordered_map<size_t, JumpLabel*> jumpMap;
95
96#define BYTECODE_BASELINE_HANDLER(name) void Handle##name(const uint8_t *bytecodeArray);
97    ECMA_OPCODE_LIST(BYTECODE_BASELINE_HANDLER)
98#undef BYTECODE_BASELINE_HANDLER
99    const uint8_t *pfHeaderAddr = nullptr;
100    const uint8_t *firstPC = nullptr;
101    static constexpr uint32_t ONE_BYTE_SIZE = 8;
102    static constexpr uint32_t TWO_BYTE_SIZE = 16;
103    static constexpr uint32_t THREE_BYTE_SIZE = 24;
104    BytecodeNativePcOffsetTable nativePcOffsetTable;
105};
106}  // namespace panda::ecmascript::kungfu
107#endif  // ECMASCRIPT_COMPILER_BASELINE_BASELINE_COMPILER_H
108