1b1994897Sopenharmony_ci/**
2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License.
5b1994897Sopenharmony_ci * You may obtain a copy of the License at
6b1994897Sopenharmony_ci *
7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8b1994897Sopenharmony_ci *
9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and
13b1994897Sopenharmony_ci * limitations under the License.
14b1994897Sopenharmony_ci */
15b1994897Sopenharmony_ci
16b1994897Sopenharmony_ci#ifndef ASSEMBLER_ASSEMBLY_FUNCTION_H
17b1994897Sopenharmony_ci#define ASSEMBLER_ASSEMBLY_FUNCTION_H
18b1994897Sopenharmony_ci
19b1994897Sopenharmony_ci#include <memory>
20b1994897Sopenharmony_ci#include <optional>
21b1994897Sopenharmony_ci#include <string>
22b1994897Sopenharmony_ci#include <string_view>
23b1994897Sopenharmony_ci#include <unordered_map>
24b1994897Sopenharmony_ci#include <vector>
25b1994897Sopenharmony_ci
26b1994897Sopenharmony_ci#include "assembly-ins.h"
27b1994897Sopenharmony_ci#include "assembly-label.h"
28b1994897Sopenharmony_ci#include "assembly-type.h"
29b1994897Sopenharmony_ci#include "assembly-debug.h"
30b1994897Sopenharmony_ci#include "assembly-file-location.h"
31b1994897Sopenharmony_ci#include "bytecode_emitter.h"
32b1994897Sopenharmony_ci#include "extensions/extensions.h"
33b1994897Sopenharmony_ci#include "file_items.h"
34b1994897Sopenharmony_ci#include "file_item_container.h"
35b1994897Sopenharmony_ci#include "ide_helpers.h"
36b1994897Sopenharmony_ci#include "meta.h"
37b1994897Sopenharmony_ci
38b1994897Sopenharmony_cinamespace panda::pandasm {
39b1994897Sopenharmony_ci
40b1994897Sopenharmony_cistruct Function {
41b1994897Sopenharmony_ci    struct CatchBlock {
42b1994897Sopenharmony_ci        std::string whole_line;
43b1994897Sopenharmony_ci        std::string exception_record;
44b1994897Sopenharmony_ci        std::string try_begin_label;
45b1994897Sopenharmony_ci        std::string try_end_label;
46b1994897Sopenharmony_ci        std::string catch_begin_label;
47b1994897Sopenharmony_ci        std::string catch_end_label;
48b1994897Sopenharmony_ci    };
49b1994897Sopenharmony_ci
50b1994897Sopenharmony_ci    struct TryCatchInfo {
51b1994897Sopenharmony_ci        std::unordered_map<std::string_view, size_t> try_catch_labels;
52b1994897Sopenharmony_ci        std::unordered_map<std::string, std::vector<const CatchBlock *>> try_catch_map;
53b1994897Sopenharmony_ci        std::vector<std::string> try_catch_order;
54b1994897Sopenharmony_ci        TryCatchInfo(std::unordered_map<std::string_view, size_t> &labels,
55b1994897Sopenharmony_ci                     std::unordered_map<std::string, std::vector<const CatchBlock *>> &map,
56b1994897Sopenharmony_ci                     std::vector<std::string> &param_try_catch_order)
57b1994897Sopenharmony_ci            : try_catch_labels(labels), try_catch_map(map), try_catch_order(param_try_catch_order)
58b1994897Sopenharmony_ci        {
59b1994897Sopenharmony_ci        }
60b1994897Sopenharmony_ci    };
61b1994897Sopenharmony_ci
62b1994897Sopenharmony_ci    struct Parameter {
63b1994897Sopenharmony_ci        Type type;
64b1994897Sopenharmony_ci        std::unique_ptr<ParamMetadata> metadata;
65b1994897Sopenharmony_ci
66b1994897Sopenharmony_ci        Parameter(Type t, panda::panda_file::SourceLang lang)
67b1994897Sopenharmony_ci            : type(std::move(t)), metadata(extensions::MetadataExtension::CreateParamMetadata(lang))
68b1994897Sopenharmony_ci        {
69b1994897Sopenharmony_ci        }
70b1994897Sopenharmony_ci    };
71b1994897Sopenharmony_ci
72b1994897Sopenharmony_ci    std::string name = "";
73b1994897Sopenharmony_ci    panda::panda_file::SourceLang language;
74b1994897Sopenharmony_ci    std::unique_ptr<FunctionMetadata> metadata;
75b1994897Sopenharmony_ci
76b1994897Sopenharmony_ci    std::unordered_map<std::string, panda::pandasm::Label> label_table;
77b1994897Sopenharmony_ci    std::vector<panda::pandasm::Ins> ins; /* function instruction list */
78b1994897Sopenharmony_ci    std::vector<panda::pandasm::debuginfo::LocalVariable> local_variable_debug;
79b1994897Sopenharmony_ci    std::string source_file; /* The file in which the function is defined or empty */
80b1994897Sopenharmony_ci    std::string source_code;
81b1994897Sopenharmony_ci    std::vector<CatchBlock> catch_blocks;
82b1994897Sopenharmony_ci    int64_t value_of_first_param = -1;
83b1994897Sopenharmony_ci    size_t regs_num = 0;
84b1994897Sopenharmony_ci    std::vector<Parameter> params;
85b1994897Sopenharmony_ci    bool body_presence = false;
86b1994897Sopenharmony_ci    Type return_type;
87b1994897Sopenharmony_ci    SourceLocation body_location;
88b1994897Sopenharmony_ci    std::optional<FileLocation> file_location;
89b1994897Sopenharmony_ci    panda::panda_file::FunctionKind function_kind = panda::panda_file::FunctionKind::NONE;
90b1994897Sopenharmony_ci    size_t slots_num = 0;
91b1994897Sopenharmony_ci    std::vector<int> concurrent_module_requests;
92b1994897Sopenharmony_ci
93b1994897Sopenharmony_ci    void SetSlotsNum(size_t num)
94b1994897Sopenharmony_ci    {
95b1994897Sopenharmony_ci        slots_num = num;
96b1994897Sopenharmony_ci    }
97b1994897Sopenharmony_ci
98b1994897Sopenharmony_ci    size_t GetSlotsNum() const
99b1994897Sopenharmony_ci    {
100b1994897Sopenharmony_ci        return slots_num;
101b1994897Sopenharmony_ci    }
102b1994897Sopenharmony_ci
103b1994897Sopenharmony_ci    void SetFunctionKind(panda::panda_file::FunctionKind kind)
104b1994897Sopenharmony_ci    {
105b1994897Sopenharmony_ci        function_kind = kind;
106b1994897Sopenharmony_ci    }
107b1994897Sopenharmony_ci
108b1994897Sopenharmony_ci    panda::panda_file::FunctionKind GetFunctionKind() const
109b1994897Sopenharmony_ci    {
110b1994897Sopenharmony_ci        return function_kind;
111b1994897Sopenharmony_ci    }
112b1994897Sopenharmony_ci
113b1994897Sopenharmony_ci    void SetInsDebug(const std::vector<debuginfo::Ins> &ins_debug)
114b1994897Sopenharmony_ci    {
115b1994897Sopenharmony_ci        ASSERT(ins_debug.size() == ins.size());
116b1994897Sopenharmony_ci        for (std::size_t i = 0; i < ins.size(); i++) {
117b1994897Sopenharmony_ci            ins[i].ins_debug = ins_debug[i];
118b1994897Sopenharmony_ci        }
119b1994897Sopenharmony_ci    }
120b1994897Sopenharmony_ci
121b1994897Sopenharmony_ci    void AddInstruction(const panda::pandasm::Ins &instruction)
122b1994897Sopenharmony_ci    {
123b1994897Sopenharmony_ci        ins.emplace_back(instruction);
124b1994897Sopenharmony_ci    }
125b1994897Sopenharmony_ci
126b1994897Sopenharmony_ci    Function(std::string s, panda::panda_file::SourceLang lang, size_t b_l, size_t b_r, std::string f_c, bool d,
127b1994897Sopenharmony_ci             size_t l_n)
128b1994897Sopenharmony_ci        : name(std::move(s)),
129b1994897Sopenharmony_ci          language(lang),
130b1994897Sopenharmony_ci          metadata(extensions::MetadataExtension::CreateFunctionMetadata(lang)),
131b1994897Sopenharmony_ci          file_location({f_c, b_l, b_r, l_n, d})
132b1994897Sopenharmony_ci    {
133b1994897Sopenharmony_ci    }
134b1994897Sopenharmony_ci
135b1994897Sopenharmony_ci    Function(std::string s, panda::panda_file::SourceLang lang)
136b1994897Sopenharmony_ci        : name(std::move(s)), language(lang), metadata(extensions::MetadataExtension::CreateFunctionMetadata(lang))
137b1994897Sopenharmony_ci    {
138b1994897Sopenharmony_ci    }
139b1994897Sopenharmony_ci
140b1994897Sopenharmony_ci    std::size_t GetParamsNum() const
141b1994897Sopenharmony_ci    {
142b1994897Sopenharmony_ci        return params.size();
143b1994897Sopenharmony_ci    }
144b1994897Sopenharmony_ci
145b1994897Sopenharmony_ci    std::size_t GetTotalRegs() const
146b1994897Sopenharmony_ci    {
147b1994897Sopenharmony_ci        return regs_num;
148b1994897Sopenharmony_ci    }
149b1994897Sopenharmony_ci
150b1994897Sopenharmony_ci    bool IsStatic() const
151b1994897Sopenharmony_ci    {
152b1994897Sopenharmony_ci        return (metadata->GetAccessFlags() & ACC_STATIC) != 0;
153b1994897Sopenharmony_ci    }
154b1994897Sopenharmony_ci
155b1994897Sopenharmony_ci    bool Emit(BytecodeEmitter &emitter, panda_file::MethodItem *method,
156b1994897Sopenharmony_ci              const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods,
157b1994897Sopenharmony_ci              const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
158b1994897Sopenharmony_ci              const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes,
159b1994897Sopenharmony_ci              const std::unordered_map<std::string, panda_file::StringItem *> &strings,
160b1994897Sopenharmony_ci              const std::unordered_map<std::string, panda_file::LiteralArrayItem *> &literalarrays) const;
161b1994897Sopenharmony_ci
162b1994897Sopenharmony_ci    size_t GetLineNumber(size_t i) const;
163b1994897Sopenharmony_ci
164b1994897Sopenharmony_ci    uint32_t GetColumnNumber(size_t i) const;
165b1994897Sopenharmony_ci
166b1994897Sopenharmony_ci    struct LocalVariablePair {
167b1994897Sopenharmony_ci        size_t insn_order;
168b1994897Sopenharmony_ci        size_t variable_index;
169b1994897Sopenharmony_ci        LocalVariablePair(size_t order, size_t index) : insn_order(order), variable_index(index) {}
170b1994897Sopenharmony_ci    };
171b1994897Sopenharmony_ci    void CollectLocalVariable(std::vector<LocalVariablePair> &local_variable_info) const;
172b1994897Sopenharmony_ci    void EmitLocalVariable(panda_file::LineNumberProgramItem *program, panda_file::ItemContainer *container,
173b1994897Sopenharmony_ci                           std::vector<uint8_t> *constant_pool, uint32_t &pc_inc, size_t instruction_number,
174b1994897Sopenharmony_ci                           size_t variable_index) const;
175b1994897Sopenharmony_ci    void EmitNumber(panda_file::LineNumberProgramItem *program, std::vector<uint8_t> *constant_pool, uint32_t pc_inc,
176b1994897Sopenharmony_ci                    int32_t line_inc) const;
177b1994897Sopenharmony_ci    void EmitLineNumber(panda_file::LineNumberProgramItem *program, std::vector<uint8_t> *constant_pool,
178b1994897Sopenharmony_ci                        int32_t &prev_line_number, uint32_t &pc_inc, size_t instruction_number) const;
179b1994897Sopenharmony_ci
180b1994897Sopenharmony_ci    // column number is only for dynamic language now
181b1994897Sopenharmony_ci    void EmitColumnNumber(panda_file::LineNumberProgramItem *program, std::vector<uint8_t> *constant_pool,
182b1994897Sopenharmony_ci                          uint32_t &prev_column_number, uint32_t &pc_inc, size_t instruction_number) const;
183b1994897Sopenharmony_ci
184b1994897Sopenharmony_ci    void BuildLineNumberProgram(panda_file::DebugInfoItem *debug_item, const std::vector<uint8_t> &bytecode,
185b1994897Sopenharmony_ci                                panda_file::ItemContainer *container, std::vector<uint8_t> *constant_pool,
186b1994897Sopenharmony_ci                                bool emit_debug_info) const;
187b1994897Sopenharmony_ci
188b1994897Sopenharmony_ci    Function::TryCatchInfo MakeOrderAndOffsets(const std::vector<uint8_t> &bytecode) const;
189b1994897Sopenharmony_ci
190b1994897Sopenharmony_ci    std::vector<panda_file::CodeItem::TryBlock> BuildTryBlocks(
191b1994897Sopenharmony_ci        panda_file::MethodItem *method, const std::unordered_map<std::string, panda_file::BaseClassItem *> &class_items,
192b1994897Sopenharmony_ci        const std::vector<uint8_t> &bytecode) const;
193b1994897Sopenharmony_ci
194b1994897Sopenharmony_ci    bool HasImplementation() const
195b1994897Sopenharmony_ci    {
196b1994897Sopenharmony_ci        return !metadata->IsForeign();
197b1994897Sopenharmony_ci    }
198b1994897Sopenharmony_ci
199b1994897Sopenharmony_ci    bool IsParameter(uint32_t reg_number) const
200b1994897Sopenharmony_ci    {
201b1994897Sopenharmony_ci        return reg_number >= regs_num;
202b1994897Sopenharmony_ci    }
203b1994897Sopenharmony_ci
204b1994897Sopenharmony_ci    bool CanThrow() const
205b1994897Sopenharmony_ci    {
206b1994897Sopenharmony_ci        return std::any_of(ins.cbegin(), ins.cend(), [](const Ins &insn) { return insn.CanThrow(); });
207b1994897Sopenharmony_ci    }
208b1994897Sopenharmony_ci
209b1994897Sopenharmony_ci    bool HasDebugInfo() const
210b1994897Sopenharmony_ci    {
211b1994897Sopenharmony_ci        return std::any_of(ins.cbegin(), ins.cend(), [](const Ins &insn) { return insn.HasDebugInfo(); });
212b1994897Sopenharmony_ci    }
213b1994897Sopenharmony_ci
214b1994897Sopenharmony_ci    void DebugDump() const;
215b1994897Sopenharmony_ci
216b1994897Sopenharmony_ci    std::set<std::string> CollectStringsFromFunctionInsns() const;
217b1994897Sopenharmony_ci};
218b1994897Sopenharmony_ci
219b1994897Sopenharmony_ci}  // namespace panda::pandasm
220b1994897Sopenharmony_ci
221b1994897Sopenharmony_ci#endif  // ASSEMBLER_ASSEMBLY_FUNCTION_H
222