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 #include "abc_module_array_processor.h"
17 
18 namespace panda::abc2program {
19 
AbcModuleArrayProcessor(panda_file::File::EntityId entity_id, Abc2ProgramEntityContainer &entity_container)20 AbcModuleArrayProcessor::AbcModuleArrayProcessor(panda_file::File::EntityId entity_id,
21                                                  Abc2ProgramEntityContainer &entity_container)
22     : AbcFileEntityProcessor(entity_id, entity_container)
23 {
24     module_data_accessor_ = std::make_unique<panda_file::ModuleDataAccessor>(*file_, entity_id_);
25 }
26 
FillProgramData()27 void AbcModuleArrayProcessor::FillProgramData()
28 {
29     const std::vector<uint32_t> &request_modules_offset = module_data_accessor_->getRequestModules();
30     std::vector<panda::pandasm::LiteralArray::Literal> literal_vec;
31     FillModuleRequests(literal_vec, request_modules_offset);
32     uint32_t regular_import_num = 0;
33     uint32_t namespace_import_num = 0;
34     uint32_t local_export_num = 0;
35     uint32_t indirect_export_num = 0;
36     uint32_t star_export_num = 0;
37     module_data_accessor_->EnumerateModuleRecord([&](panda_file::ModuleTag tag, uint32_t export_name_offset,
38         uint32_t request_module_idx, uint32_t import_name_offset, uint32_t local_name_offset) {
39         switch (tag) {
40             case panda_file::ModuleTag::REGULAR_IMPORT:
41                 FillRegularImportEntry(literal_vec, request_module_idx, import_name_offset, local_name_offset);
42                 ++regular_import_num;
43                 break;
44             case panda_file::ModuleTag::NAMESPACE_IMPORT:
45                 FillNamespaceImportEntry(literal_vec, request_module_idx, local_name_offset);
46                 ++namespace_import_num;
47                 break;
48             case panda_file::ModuleTag::LOCAL_EXPORT:
49                 FillLocalExportEntry(literal_vec, export_name_offset, local_name_offset);
50                 ++local_export_num;
51                 break;
52             case panda_file::ModuleTag::INDIRECT_EXPORT:
53                 FillIndirectExportEntry(literal_vec, export_name_offset, request_module_idx, import_name_offset);
54                 ++indirect_export_num;
55                 break;
56             case panda_file::ModuleTag::STAR_EXPORT:
57                 FillStarExportEntry(literal_vec, request_module_idx);
58                 ++star_export_num;
59                 break;
60             default: {
61                 UNREACHABLE();
62             }
63         }
64     });
65     std::vector<uint32_t> num_vec = {request_modules_offset.size(), regular_import_num, namespace_import_num,
66         local_export_num, indirect_export_num, star_export_num};
67     FillEntrySize(literal_vec, num_vec);
68     auto module_array = panda::pandasm::LiteralArray(std::move(literal_vec));
69     program_->literalarray_table.emplace(entity_container_.GetLiteralArrayIdName(entity_id_.GetOffset()),
70                                          std::move(module_array));
71 }
72 
FillModuleRequests(std::vector<panda::pandasm::LiteralArray::Literal> &literal_vec, const std::vector<uint32_t> &request_modules_offset)73 void AbcModuleArrayProcessor::FillModuleRequests(std::vector<panda::pandasm::LiteralArray::Literal> &literal_vec,
74     const std::vector<uint32_t> &request_modules_offset)
75 {
76     panda::pandasm::LiteralArray::Literal module_size = {
77         .tag_ = panda::panda_file::LiteralTag::INTEGER,
78         .value_ = static_cast<uint32_t>(request_modules_offset.size())
79     };
80     literal_vec.emplace_back(module_size);
81     for (auto &request : request_modules_offset) {
82         panda::pandasm::LiteralArray::Literal module_request = {
83             .tag_ = panda::panda_file::LiteralTag::STRING,
84             .value_ = GetStringById(panda_file::File::EntityId{request})
85         };
86         literal_vec.emplace_back(module_request);
87     }
88 }
89 
FillRegularImportEntry(std::vector<panda::pandasm::LiteralArray::Literal> &literal_vec, uint32_t &request_module_idx, uint32_t &import_name_offset, uint32_t &local_name_offset)90 void AbcModuleArrayProcessor::FillRegularImportEntry(std::vector<panda::pandasm::LiteralArray::Literal> &literal_vec,
91     uint32_t &request_module_idx, uint32_t &import_name_offset, uint32_t &local_name_offset)
92 {
93     panda::pandasm::LiteralArray::Literal local_name = {
94         .tag_ = panda::panda_file::LiteralTag::STRING,
95         .value_ = GetStringById(panda_file::File::EntityId{local_name_offset})
96     };
97     literal_vec.emplace_back(local_name);
98     panda::pandasm::LiteralArray::Literal import_name = {
99         .tag_ = panda::panda_file::LiteralTag::STRING,
100         .value_ = GetStringById(panda_file::File::EntityId{import_name_offset})
101     };
102     literal_vec.emplace_back(import_name);
103     panda::pandasm::LiteralArray::Literal module_request = {
104         .tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE,
105         .value_ = static_cast<uint16_t>(request_module_idx)
106     };
107     literal_vec.emplace_back(module_request);
108 }
109 
FillNamespaceImportEntry( std::vector<panda::pandasm::LiteralArray::Literal> &literal_vec, uint32_t &request_module_idx, uint32_t &local_name_offset)110 void AbcModuleArrayProcessor::FillNamespaceImportEntry(
111     std::vector<panda::pandasm::LiteralArray::Literal> &literal_vec,
112     uint32_t &request_module_idx, uint32_t &local_name_offset)
113 {
114     panda::pandasm::LiteralArray::Literal local_name = {
115         .tag_ = panda::panda_file::LiteralTag::STRING,
116         .value_ = GetStringById(panda_file::File::EntityId{local_name_offset})
117     };
118     literal_vec.emplace_back(local_name);
119     panda::pandasm::LiteralArray::Literal module_request = {
120         .tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE,
121         .value_ = static_cast<uint16_t>(request_module_idx)
122     };
123     literal_vec.emplace_back(module_request);
124 }
125 
FillLocalExportEntry(std::vector<panda::pandasm::LiteralArray::Literal> &literal_vec, uint32_t export_name_offset, uint32_t &local_name_offset)126 void AbcModuleArrayProcessor::FillLocalExportEntry(std::vector<panda::pandasm::LiteralArray::Literal> &literal_vec,
127     uint32_t export_name_offset, uint32_t &local_name_offset)
128 {
129     panda::pandasm::LiteralArray::Literal local_name = {
130         .tag_ = panda::panda_file::LiteralTag::STRING,
131         .value_ = GetStringById(panda_file::File::EntityId{local_name_offset})
132     };
133     literal_vec.emplace_back(local_name);
134     panda::pandasm::LiteralArray::Literal export_name = {
135         .tag_ = panda::panda_file::LiteralTag::STRING,
136         .value_ = GetStringById(panda_file::File::EntityId{export_name_offset})
137     };
138     literal_vec.emplace_back(export_name);
139 }
140 
FillIndirectExportEntry(std::vector<panda::pandasm::LiteralArray::Literal> &literal_vec, uint32_t export_name_offset, uint32_t request_module_idx, uint32_t import_name_offset)141 void AbcModuleArrayProcessor::FillIndirectExportEntry(std::vector<panda::pandasm::LiteralArray::Literal> &literal_vec,
142     uint32_t export_name_offset, uint32_t request_module_idx, uint32_t import_name_offset)
143 {
144     panda::pandasm::LiteralArray::Literal export_name = {
145         .tag_ = panda::panda_file::LiteralTag::STRING,
146         .value_ = GetStringById(panda_file::File::EntityId{export_name_offset})
147     };
148     literal_vec.emplace_back(export_name);
149     panda::pandasm::LiteralArray::Literal import_name = {
150         .tag_ = panda::panda_file::LiteralTag::STRING,
151         .value_ = GetStringById(panda_file::File::EntityId{import_name_offset})
152     };
153     literal_vec.emplace_back(import_name);
154     panda::pandasm::LiteralArray::Literal module_request = {
155         .tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE,
156         .value_ = static_cast<uint16_t>(request_module_idx)
157     };
158     literal_vec.emplace_back(module_request);
159 }
160 
FillStarExportEntry(std::vector<panda::pandasm::LiteralArray::Literal> &literal_vec, uint32_t request_module_idx)161 void AbcModuleArrayProcessor::FillStarExportEntry(std::vector<panda::pandasm::LiteralArray::Literal> &literal_vec,
162     uint32_t request_module_idx)
163 {
164     panda::pandasm::LiteralArray::Literal module_request = {
165         .tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE,
166         .value_ = static_cast<uint16_t>(request_module_idx)
167     };
168     literal_vec.emplace_back(module_request);
169 }
170 
171 // Add the literal of the size of various attributes in the module literal array.
FillEntrySize(std::vector<panda::pandasm::LiteralArray::Literal> &literal_vec, const std::vector<uint32_t> &num_vec)172 void AbcModuleArrayProcessor::FillEntrySize(std::vector<panda::pandasm::LiteralArray::Literal> &literal_vec,
173     const std::vector<uint32_t> &num_vec)
174 {
175     // Insert literals of regular_import_num, namespace_import_num, local_export_num,
176     // indirect_export_num, star_export_num to literal_vec.
177     uint32_t idx_num = num_vec[0] + 1;
178     for (size_t index = 1; index < num_vec.size(); ++index) {
179         auto num = num_vec[index];
180         panda::pandasm::LiteralArray::Literal entry_size = {
181             .tag_ = panda::panda_file::LiteralTag::INTEGER,
182             .value_ = static_cast<uint32_t>(num)
183         };
184         literal_vec.insert(literal_vec.begin() + idx_num, entry_size);
185         // '1' stands for each entry_size, which has been inserted into literal vec
186         idx_num += 1;
187         ASSERT(index - 1 < sizeof(LITERAL_NUMS)/sizeof(LITERAL_NUMS[0]));
188         // skip total num of module literals for each module kind
189         idx_num += LITERAL_NUMS[index-1] * num;
190     }
191 }
192 }  // namespace panda::abc2program