1 /*
2  * Copyright (c) 2021 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 "moduleRecordEmitter.h"
17 
18 namespace panda::es2panda::compiler {
GenModuleRequests()19 void ModuleRecordEmitter::GenModuleRequests()
20 {
21     ASSERT(moduleRecord_ != nullptr);
22     auto &moduleRequests = moduleRecord_->GetModuleRequests();
23     panda::pandasm::LiteralArray::Literal moduleSize = {
24         .tag_ = panda::panda_file::LiteralTag::INTEGER, .value_ = static_cast<uint32_t>(moduleRequests.size())};
25     buffer_.emplace_back(moduleSize);
26     for (auto request : moduleRequests) {
27         panda::pandasm::LiteralArray::Literal moduleRequest = {
28             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = (request.source_).Mutf8()};
29         buffer_.emplace_back(moduleRequest);
30 
31         if (!NeedEmitPhaseRecord()) {
32             continue;
33         }
34         panda::pandasm::LiteralArray::Literal moduleRequestPhase = {
35             .tag_ = panda::panda_file::LiteralTag::INTEGER_8, .value_ = static_cast<uint8_t>(request.isLazy_)};
36         phaseBuffer_.emplace_back(moduleRequestPhase);
37     }
38 }
39 
GenRegularImportEntries()40 void ModuleRecordEmitter::GenRegularImportEntries()
41 {
42     ASSERT(moduleRecord_ != nullptr);
43     auto &regularImportEntries = moduleRecord_->GetRegularImportEntries();
44     panda::pandasm::LiteralArray::Literal entrySize = {
45         .tag_ = panda::panda_file::LiteralTag::INTEGER,
46         .value_ = static_cast<uint32_t>(regularImportEntries.size())};
47     buffer_.emplace_back(entrySize);
48     for (auto it = regularImportEntries.begin(); it != regularImportEntries.end(); ++it) {
49         auto *entry = it->second;
50         panda::pandasm::LiteralArray::Literal localName = {
51             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = entry->localName_.Mutf8()};
52         buffer_.emplace_back(localName);
53         panda::pandasm::LiteralArray::Literal importName = {
54             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = entry->importName_.Mutf8()};
55         buffer_.emplace_back(importName);
56         panda::pandasm::LiteralArray::Literal moduleRequest = {
57             .tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE,
58             .value_ = static_cast<uint16_t>(entry->moduleRequestIdx_)};
59         buffer_.emplace_back(moduleRequest);
60     }
61 }
62 
GenNamespaceImportEntries()63 void ModuleRecordEmitter::GenNamespaceImportEntries()
64 {
65     ASSERT(moduleRecord_ != nullptr);
66     auto &namespaceImportEntries = moduleRecord_->GetNamespaceImportEntries();
67     panda::pandasm::LiteralArray::Literal entrySize = {
68         .tag_ = panda::panda_file::LiteralTag::INTEGER,
69         .value_ = static_cast<uint32_t>(namespaceImportEntries.size())};
70     buffer_.emplace_back(entrySize);
71     for (const auto *entry : namespaceImportEntries) {
72         panda::pandasm::LiteralArray::Literal localName = {
73             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = entry->localName_.Mutf8()};
74         buffer_.emplace_back(localName);
75         panda::pandasm::LiteralArray::Literal moduleRequest = {
76             .tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE,
77             .value_ = static_cast<uint16_t>(entry->moduleRequestIdx_)};
78         buffer_.emplace_back(moduleRequest);
79     }
80 }
81 
GenLocalExportEntries()82 void ModuleRecordEmitter::GenLocalExportEntries()
83 {
84     ASSERT(moduleRecord_ != nullptr);
85     auto &localExportEntries = moduleRecord_->GetLocalExportEntries();
86     panda::pandasm::LiteralArray::Literal entrySize = {
87         .tag_ = panda::panda_file::LiteralTag::INTEGER, .value_ = static_cast<uint32_t>(localExportEntries.size())};
88     buffer_.emplace_back(entrySize);
89     std::unordered_set<std::string> local_export_local_names;
90     for (auto it = localExportEntries.begin(); it != localExportEntries.end(); ++it) {
91         auto *entry = it->second;
92         panda::pandasm::LiteralArray::Literal localName = {
93             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = entry->localName_.Mutf8()};
94         buffer_.emplace_back(localName);
95         panda::pandasm::LiteralArray::Literal exportName = {
96             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = entry->exportName_.Mutf8()};
97         buffer_.emplace_back(exportName);
98         // Slot of stmodulevar/ldlocalmodulevar is the index of its local name, while
99         // one local name can match multiple external names with "export...as...".
100         // Local export entries are sorted by their local name, thus using an unrodered_set
101         // can get the correct index form (size - 1) (starts from 0).
102         // See SourceTextModuleRecord::AssignIndexToModuleVariable for more details
103         local_export_local_names.emplace(entry->localName_);
104         if (entry->isConstant_) {
105             constant_local_export_slots_.emplace(local_export_local_names.size() - 1);
106         }
107     }
108 }
109 
GenIndirectExportEntries()110 void ModuleRecordEmitter::GenIndirectExportEntries()
111 {
112     ASSERT(moduleRecord_ != nullptr);
113     auto &indirectExportEntries = moduleRecord_->GetIndirectExportEntries();
114     panda::pandasm::LiteralArray::Literal entrySize = {
115         .tag_ = panda::panda_file::LiteralTag::INTEGER, .value_ = static_cast<uint32_t>(indirectExportEntries.size())};
116     buffer_.emplace_back(entrySize);
117     for (const auto *entry : indirectExportEntries) {
118         panda::pandasm::LiteralArray::Literal exportName = {
119             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = entry->exportName_.Mutf8()};
120         buffer_.emplace_back(exportName);
121         panda::pandasm::LiteralArray::Literal importName = {
122             .tag_ = panda::panda_file::LiteralTag::STRING, .value_ = entry->importName_.Mutf8()};
123         buffer_.emplace_back(importName);
124         panda::pandasm::LiteralArray::Literal moduleRequest = {
125             .tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE,
126             .value_ = static_cast<uint16_t>(entry->moduleRequestIdx_)};
127         buffer_.emplace_back(moduleRequest);
128     }
129 }
130 
GenStarExportEntries()131 void ModuleRecordEmitter::GenStarExportEntries()
132 {
133     ASSERT(moduleRecord_ != nullptr);
134     auto &starExportEntries = moduleRecord_->GetStarExportEntries();
135     panda::pandasm::LiteralArray::Literal entrySize = {
136         .tag_ = panda::panda_file::LiteralTag::INTEGER, .value_ = static_cast<uint32_t>(starExportEntries.size())};
137     buffer_.emplace_back(entrySize);
138     for (const auto *entry : starExportEntries) {
139         panda::pandasm::LiteralArray::Literal moduleRequest = {
140             .tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE,
141             .value_ = static_cast<uint16_t>(entry->moduleRequestIdx_)};
142         buffer_.emplace_back(moduleRequest);
143     }
144 }
145 
Generate()146 void ModuleRecordEmitter::Generate()
147 {
148     GenModuleRequests();
149     GenRegularImportEntries();
150     GenNamespaceImportEntries();
151     GenLocalExportEntries();
152     GenIndirectExportEntries();
153     GenStarExportEntries();
154 }
155 }  // namespace panda::es2panda::compiler
156