1/*
2 * Copyright (c) 2023-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#ifndef ECMASCRIPT_COMPILER_AOT_FILE_AOT_FILE_INFO_H
16#define ECMASCRIPT_COMPILER_AOT_FILE_AOT_FILE_INFO_H
17
18#include "ecmascript/common.h"
19#include "ecmascript/compiler/aot_file/executed_memory_allocator.h"
20#include "ecmascript/compiler/aot_file/module_section_des.h"
21#include "ecmascript/compiler/bc_call_signature.h"
22#include "ecmascript/deoptimizer/calleeReg.h"
23#include "ecmascript/compiler/aot_file/func_entry_des.h"
24#include "ecmascript/stackmap/ark_stackmap.h"
25
26namespace panda::ecmascript {
27class PUBLIC_API AOTFileInfo {
28public:
29    using FuncEntryDes = ecmascript::FuncEntryDes;
30    using CallSignature = kungfu::CallSignature;
31    using CalleeRegAndOffsetVec = kungfu::CalleeRegAndOffsetVec;
32    using DwarfRegType = kungfu::LLVMStackMapType::DwarfRegType;
33    using OffsetType = kungfu::LLVMStackMapType::OffsetType;
34    using DwarfRegAndOffsetType = kungfu::LLVMStackMapType::DwarfRegAndOffsetType;
35    AOTFileInfo() = default;
36    virtual ~AOTFileInfo() = default;
37
38    static constexpr uint32_t TEXT_SEC_ALIGN = 16;
39    static constexpr uint32_t DATA_SEC_ALIGN = 8;
40    static constexpr uint32_t PAGE_ALIGN = 4096;
41
42    const FuncEntryDes &GetStubDes(int index) const
43    {
44        return entries_[index];
45    }
46
47    uint32_t GetEntrySize() const
48    {
49        return entries_.size();
50    }
51
52    const std::vector<FuncEntryDes> &GetStubs() const
53    {
54        return entries_;
55    }
56
57    const std::vector<ModuleSectionDes> &GetCodeUnits() const
58    {
59        return des_;
60    }
61
62    uint32_t GetStubNum() const
63    {
64        return entryNum_;
65    }
66
67    void SetStubNum(uint32_t n)
68    {
69        entryNum_ = n;
70    }
71
72    void AddEntry(CallSignature::TargetKind kind, bool isMainFunc, bool isFastCall, int indexInKind, uint64_t offset,
73                  uint32_t fileIndex, uint32_t moduleIndex, int delta, uint32_t size, CalleeRegAndOffsetVec info = {})
74    {
75        FuncEntryDes des;
76        if (memset_s(&des, sizeof(des), 0, sizeof(des)) != EOK) {
77            LOG_FULL(FATAL) << "memset_s failed";
78            return;
79        }
80        des.kind_ = kind;
81        des.isMainFunc_ = isMainFunc;
82        des.isFastCall_ = isFastCall;
83        des.indexInKindOrMethodId_ = static_cast<uint32_t>(indexInKind);
84        des.abcIndexInAi_ = fileIndex;
85        des.codeAddr_ = offset;
86        des.moduleIndex_ = moduleIndex;
87        des.fpDeltaPrevFrameSp_ = delta;
88        des.funcSize_ = size;
89        des.calleeRegisterNum_ = info.size();
90        DwarfRegType reg = 0;
91        OffsetType regOffset = 0;
92        for (size_t i = 0; i < info.size(); i++) {
93            std::tie(reg, regOffset) = info[i];
94            des.CalleeReg2Offset_[2 * i] = static_cast<int32_t>(reg);
95            des.CalleeReg2Offset_[2 * i + 1] = static_cast<int32_t>(regOffset);
96        }
97        entries_.emplace_back(des);
98    }
99
100    const std::vector<ModuleSectionDes> &GetModuleSectionDes() const
101    {
102        return des_;
103    }
104
105    void UpdateStackMap(std::shared_ptr<uint8_t> ptr, uint32_t size, uint32_t moduleIdx)
106    {
107        ASSERT(moduleIdx < des_.size());
108        ModuleSectionDes &des = des_[moduleIdx];
109        des.SetArkStackMapPtr(ptr);
110        des.SetArkStackMapSize(size);
111    }
112
113    size_t GetCodeUnitsNum() const
114    {
115        return des_.size();
116    }
117
118    void accumulateTotalSize(uint32_t size)
119    {
120        totalCodeSize_ += size;
121    }
122
123    uint32_t GetTotalCodeSize() const
124    {
125        return totalCodeSize_;
126    }
127
128    using CallSiteInfo = std::tuple<uint64_t, uint8_t *, int, CalleeRegAndOffsetVec>;
129
130    bool CalCallSiteInfo(uintptr_t retAddr, CallSiteInfo &ret, bool isInStub, bool isDeopt) const;
131
132    virtual void Destroy();
133
134protected:
135    ExecutedMemoryAllocator::ExeMem &GetStubsMem()
136    {
137        return stubsMem_;
138    }
139
140    MemMap &GetFileMapMem()
141    {
142        return fileMapMem_;
143    }
144
145    uint32_t entryNum_ {0};
146    uint32_t moduleNum_ {0};
147    uint32_t totalCodeSize_ {0};
148    std::vector<FuncEntryDes> entries_ {};
149    std::vector<ModuleSectionDes> des_ {};
150    ExecutedMemoryAllocator::ExeMem stubsMem_ {};
151    MemMap fileMapMem_ {};
152
153private:
154    AOTFileInfo::FuncEntryDes GetFuncEntryDesWithCallsite(uintptr_t codeAddr, uint32_t startIndex,
155                                                          uint32_t funcCount) const;
156
157    void StoreCalleeRegInfo(uint32_t calleeRegNum, int32_t *calleeReg2Offset,
158                            CalleeRegAndOffsetVec &calleeRegInfo) const;
159};
160}  // namespace panda::ecmascript
161#endif  // ECMASCRIPT_COMPILER_AOT_FILE_AOT_FILE_INFO_H
162