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
16#include "assemblyFunctionProto.h"
17#include "libpandafile/file_items.h"
18
19namespace panda::proto {
20void CatchBlock::Serialize(const panda::pandasm::Function::CatchBlock &block, protoPanda::CatchBlock &protoBlock)
21{
22    protoBlock.set_wholeline(block.whole_line);
23    protoBlock.set_exceptionrecord(block.exception_record);
24    protoBlock.set_trybeginlabel(block.try_begin_label);
25    protoBlock.set_tryendlabel(block.try_end_label);
26    protoBlock.set_catchbeginlabel(block.catch_begin_label);
27    protoBlock.set_catchendlabel(block.catch_end_label);
28}
29
30void CatchBlock::Deserialize(const protoPanda::CatchBlock &protoBlock, panda::pandasm::Function::CatchBlock &block)
31{
32    block.whole_line = protoBlock.wholeline();
33    block.exception_record = protoBlock.exceptionrecord();
34    block.try_begin_label = protoBlock.trybeginlabel();
35    block.try_end_label = protoBlock.tryendlabel();
36    block.catch_begin_label = protoBlock.catchbeginlabel();
37    block.catch_end_label = protoBlock.catchendlabel();
38}
39
40void Parameter::Serialize(const panda::pandasm::Function::Parameter &param, protoPanda::Parameter &protoParam)
41{
42    auto *type = protoParam.mutable_type();
43    Type::Serialize(param.type, *type);
44    auto *metadata = protoParam.mutable_metadata();
45    ParamMetadata::Serialize(*(param.metadata), *metadata);
46}
47
48void Parameter::Deserialize(const protoPanda::Parameter &protoParam, panda::pandasm::Function::Parameter &param,
49                            panda::ArenaAllocator *allocator)
50{
51    ParamMetadata::Deserialize(protoParam.metadata(), param.metadata, allocator);
52}
53
54void Function::Serialize(const panda::pandasm::Function &function, protoPanda::Function &protoFunction)
55{
56    protoFunction.set_name(function.name);
57    protoFunction.set_language(static_cast<uint32_t>(function.language));
58
59    auto *protoFuncMeta = protoFunction.mutable_metadata();
60    FunctionMetadata::Serialize(*function.metadata, *protoFuncMeta);
61
62    for (const auto &[name, label] : function.label_table) {
63        auto *labelMap = protoFunction.add_labeltable();
64        labelMap->set_key(name);
65        auto *protoLabel = labelMap->mutable_value();
66        Label::Serialize(label, *protoLabel);
67    }
68
69    for (const auto &insn : function.ins) {
70        auto *protoIns = protoFunction.add_ins();
71        Ins::Serialize(insn, *protoIns);
72    }
73
74    for (const auto &debug : function.local_variable_debug) {
75        auto *protoDebug = protoFunction.add_localvariabledebug();
76        LocalVariable::Serialize(debug, *protoDebug);
77    }
78
79    protoFunction.set_sourcefile(function.source_file);
80    protoFunction.set_sourcecode(function.source_code);
81
82    for (const auto &block : function.catch_blocks) {
83        auto *protoBlock = protoFunction.add_catchblocks();
84        CatchBlock::Serialize(block, *protoBlock);
85    }
86
87    protoFunction.set_valueoffirstparam(function.value_of_first_param);
88    protoFunction.set_regsnum(function.regs_num);
89
90    for (const auto &param : function.params) {
91        auto *protoParam = protoFunction.add_params();
92        Parameter::Serialize(param, *protoParam);
93    }
94
95    protoFunction.set_bodypresence(function.body_presence);
96
97    auto *protoReturnType = protoFunction.mutable_returntype();
98    Type::Serialize(function.return_type, *protoReturnType);
99
100    auto *protoBodyLocation = protoFunction.mutable_bodylocation();
101    SourceLocation::Serialize(function.body_location, *protoBodyLocation);
102
103    const auto &fileLocation = function.file_location;
104    if (fileLocation.has_value()) {
105        auto *protoFileLocation = protoFunction.mutable_filelocation();
106        FileLocation::Serialize(fileLocation.value(), *protoFileLocation);
107    }
108    protoFunction.set_function_kind(static_cast<uint8_t>(function.function_kind));
109    protoFunction.set_slotsnum(function.slots_num);
110
111    for (const auto &moduleRequestId : function.concurrent_module_requests) {
112        protoFunction.add_concurrent_module_requests(moduleRequestId);
113    }
114}
115
116void Function::DeserializeLabels(const protoPanda::Function &protoFunction, panda::pandasm::Function &function,
117                                 panda::ArenaAllocator *allocator)
118{
119    function.label_table.reserve(protoFunction.labeltable_size());
120    for (const auto &labelUnit : protoFunction.labeltable()) {
121        auto &name = labelUnit.key();
122        auto &protoLabel = labelUnit.value();
123        panda::pandasm::Label label(name);
124        Label::Deserialize(protoLabel, label);
125        function.label_table.insert({name, label});
126    }
127}
128
129void Function::DeserializeProtoIns(const protoPanda::Function &protoFunction, panda::pandasm::Function &function,
130                                   panda::ArenaAllocator *allocator)
131{
132    function.ins.reserve(protoFunction.ins_size());
133    for (const auto &protoIns : protoFunction.ins()) {
134        panda::pandasm::Ins ins;
135        Ins::Deserialize(protoIns, ins);
136        function.ins.emplace_back(std::move(ins));
137    }
138}
139
140void Function::DeserializeProtoLocalVariable(const protoPanda::Function &protoFunction,
141                                             panda::pandasm::Function &function,
142                                             panda::ArenaAllocator *allocator)
143{
144    function.local_variable_debug.reserve(protoFunction.localvariabledebug_size());
145    for (const auto &protoLocalVariable : protoFunction.localvariabledebug()) {
146        panda::pandasm::debuginfo::LocalVariable localVariable;
147        LocalVariable::Deserialize(protoLocalVariable, localVariable);
148        function.local_variable_debug.emplace_back(std::move(localVariable));
149    }
150}
151
152void Function::Deserialize(const protoPanda::Function &protoFunction, panda::pandasm::Function &function,
153                           panda::ArenaAllocator *allocator)
154{
155    FunctionMetadata::Deserialize(protoFunction.metadata(), function.metadata, allocator);
156    DeserializeLabels(protoFunction, function, allocator);
157    DeserializeProtoIns(protoFunction, function, allocator);
158    DeserializeProtoLocalVariable(protoFunction, function, allocator);
159
160    function.source_file = protoFunction.sourcefile();
161    function.source_code = protoFunction.sourcecode();
162
163    function.catch_blocks.reserve(protoFunction.catchblocks_size());
164    for (const auto &protoCatchBlock : protoFunction.catchblocks()) {
165        auto *catchBlock = allocator->New<panda::pandasm::Function::CatchBlock>();
166        CHECK_NOT_NULL(catchBlock);
167        CatchBlock::Deserialize(protoCatchBlock, *catchBlock);
168        function.catch_blocks.emplace_back(std::move(*catchBlock));
169    }
170
171    function.value_of_first_param = protoFunction.valueoffirstparam();
172    function.regs_num = protoFunction.regsnum();
173
174    function.params.reserve(protoFunction.params_size());
175    for (const auto &protoParam : protoFunction.params()) {
176        auto &paramType = Type::Deserialize(protoParam.type(), allocator);
177        panda::pandasm::Function::Parameter param(paramType, panda::panda_file::SourceLang::ECMASCRIPT);
178        Parameter::Deserialize(protoParam, param, allocator);
179        function.params.emplace_back(std::move(param));
180    }
181
182    function.body_presence = protoFunction.bodypresence();
183    function.return_type = Type::Deserialize(protoFunction.returntype(), allocator);
184    SourceLocation::Deserialize(protoFunction.bodylocation(), function.body_location);
185
186    if (protoFunction.has_filelocation()) {
187        FileLocation::Deserialize(protoFunction.filelocation(), function.file_location);
188    }
189    function.SetFunctionKind(static_cast<panda::panda_file::FunctionKind>(protoFunction.function_kind()));
190    function.SetSlotsNum(protoFunction.slotsnum());
191
192    for (const auto &moduleRequestId : protoFunction.concurrent_module_requests()) {
193        function.concurrent_module_requests.emplace_back(moduleRequestId);
194    }
195}
196} // panda::proto
197