• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "typeExtractorEmitter.h"
17 
18 #include <assembly-emitter.h>
19 #include <binder/binder.h>
20 #include <compiler/core/compilerContext.h>
21 #include <compiler/core/emitter/emitter.h>
22 
23 namespace panda::es2panda::compiler {
24 
25 using AnnotationElement = panda::pandasm::AnnotationElement;
26 using ArrayValue = panda::pandasm::ArrayValue;
27 using Field = panda::pandasm::Field;
28 using Record = panda::pandasm::Record;
29 using ScalarValue = panda::pandasm::ScalarValue;
30 using Type = panda::pandasm::Type;
31 using ValueType = panda::pandasm::Value::Type;
32 
TypeExtractorEmitter(const PandaGen * pg,panda::pandasm::Function * func)33 TypeExtractorEmitter::TypeExtractorEmitter(const PandaGen *pg, panda::pandasm::Function *func) : pg_(pg), func_(func)
34 {
35     auto prog = pg_->Context()->GetEmitter()->GetProgram();
36     GenFunctionTypeInfo(prog);
37     if (IsFuncMain0(func->name, pg_->Context()->IsMergeAbc())) {
38         if (pg_->Context()->TypeRecorder()->ExportType().size() > 0U) {
39             GenExportTypeInfo(prog);
40         }
41         if (pg_->Context()->TypeRecorder()->DeclareType().size() > 0U) {
42             GenDeclareTypeInfo(prog);
43         }
44     }
45 }
46 
IsFuncMain0(const std::string & funcName,bool isMergeAbc) const47 bool TypeExtractorEmitter::IsFuncMain0(const std::string &funcName, bool isMergeAbc) const
48 {
49     std::string expectedName(binder::Binder::MAIN_FUNC_NAME);
50     if (isMergeAbc) {
51         expectedName = std::string(pg_->Context()->RecordName()) + "." + expectedName;
52     }
53     return funcName == expectedName;
54 }
55 
GenTypeInfo(const extractor::TypeRecorder * recorder,int64_t typeIndex,std::vector<Literal> & typeInfo)56 static void GenTypeInfo(const extractor::TypeRecorder *recorder, int64_t typeIndex, std::vector<Literal> &typeInfo)
57 {
58     Literal typeTag;
59     Literal typeValue;
60     typeTag.tag_ = panda::panda_file::LiteralTag::TAGVALUE;
61     if (typeIndex >= recorder->GetUserTypeIndexShift()) {
62         typeTag.value_ = static_cast<uint8_t>(panda::panda_file::LiteralTag::LITERALARRAY);
63         typeValue.tag_ = panda::panda_file::LiteralTag::LITERALARRAY;
64         typeValue.value_ = std::string(recorder->GetRecordName()) + "_" +
65             std::to_string(typeIndex - recorder->GetUserTypeIndexShift());
66     } else {
67         typeTag.value_ = static_cast<uint8_t>(panda::panda_file::LiteralTag::BUILTINTYPEINDEX);
68         typeValue.tag_ = panda::panda_file::LiteralTag::BUILTINTYPEINDEX;
69         typeValue.value_ = static_cast<uint8_t>(typeIndex);
70     }
71     typeInfo.emplace_back(typeTag);
72     typeInfo.emplace_back(typeValue);
73 }
74 
GenInsnTypeInfo(const extractor::TypeRecorder * recorder,uint32_t orderIndex,int64_t typeIndex,std::vector<Literal> & typedInsns)75 static void GenInsnTypeInfo(const extractor::TypeRecorder *recorder, uint32_t orderIndex, int64_t typeIndex,
76     std::vector<Literal> &typedInsns)
77 {
78     Literal insnOrderTag;
79     Literal insnOrderValue;
80     insnOrderTag.tag_ = panda::panda_file::LiteralTag::TAGVALUE;
81     insnOrderTag.value_ = static_cast<uint8_t>(panda::panda_file::LiteralTag::INTEGER);
82     insnOrderValue.tag_ = panda::panda_file::LiteralTag::INTEGER;
83     insnOrderValue.value_ = static_cast<uint32_t>(orderIndex);
84     typedInsns.emplace_back(insnOrderTag);
85     typedInsns.emplace_back(insnOrderValue);
86 
87     GenTypeInfo(recorder, typeIndex, typedInsns);
88 }
89 
GenFunctionTypeInfo(panda::pandasm::Program * prog)90 void TypeExtractorEmitter::GenFunctionTypeInfo(panda::pandasm::Program *prog)
91 {
92     auto recorder = pg_->Context()->TypeRecorder();
93     std::vector<Literal> typedInsns;
94     typedInsns.reserve(pg_->TypedInsns().size() * 4U);  // Expand to 4 pieces of information
95     uint32_t index = 0;
96     uint32_t remove = 0;
97     for (const auto *ins : pg_->Insns()) {
98         if (func_->ins[index].opcode == panda::pandasm::Opcode::INVALID) {
99             remove++;
100             index++;
101             continue;
102         }
103         auto t = pg_->TypedInsns().find(ins);
104         if (t != pg_->TypedInsns().end()) {
105             int64_t typeIndex = t->second;
106             uint32_t orderIndex = index;
107             if (typeIndex > extractor::TypeRecorder::PRIMITIVETYPE_ANY) {
108                 uint32_t realOrderIndex = orderIndex - remove;
109                 GenInsnTypeInfo(recorder, realOrderIndex, typeIndex, typedInsns);
110                 DCOUT << "[LOG] " << func_->name << ": " << func_->ins[index].ToString("", true, func_->regs_num) <<
111                     " | " << realOrderIndex << " | " << typeIndex << std::endl;
112             }
113         }
114         index++;
115     }
116 
117     if (pg_->TypedFunc().first != extractor::TypeRecorder::PRIMITIVETYPE_ANY) {
118         // -1 for function type
119         GenInsnTypeInfo(recorder, static_cast<uint32_t>(-1), pg_->TypedFunc().first, typedInsns);
120         DCOUT << "[LOG]" << func_->name << ": -1 | " << pg_->TypedFunc().first << std::endl;
121     }
122     if (pg_->TypedFunc().second > extractor::TypeRecorder::PRIMITIVETYPE_ANY) {
123         // -2 for method 'this' type
124         GenInsnTypeInfo(recorder, static_cast<uint32_t>(-2), pg_->TypedFunc().second, typedInsns);
125         DCOUT << "[LOG]" << func_->name << ": -2 | " << pg_->TypedFunc().second << std::endl;
126     }
127 
128     if (typedInsns.empty()) {
129         return;
130     }
131 
132     std::lock_guard<std::mutex> lock(pg_->Context()->GetEmitter()->GetEmitterLock());
133     std::string literalId = std::string(recorder->GetRecordName()) + "_" +
134         func_->name + "_" + std::to_string(literalId_--);
135     auto literalArrayInstance = panda::pandasm::LiteralArray(std::move(typedInsns));
136     prog->literalarray_table.emplace(literalId, std::move(literalArrayInstance));
137 
138     AnnotationData funcTypeAnnotation(TypeExtractorEmitter::TYPE_ANNOTATION);
139     AnnotationElement funcTypeAnnotationElement(TypeExtractorEmitter::TYPE_INSTRUCTION,
140         std::make_unique<ScalarValue>(ScalarValue::Create<ValueType::LITERALARRAY>(literalId)));
141     funcTypeAnnotation.AddElement(std::move(funcTypeAnnotationElement));
142     func_->metadata->AddAnnotations({ funcTypeAnnotation });
143 }
144 
145 template <bool isExport, typename M>
GenImportOrDeclareTypeInfo(panda::pandasm::Program * prog,const extractor::TypeRecorder * recorder,const M & map,AnnotationData & funcTypeAnnotation)146 void TypeExtractorEmitter::GenImportOrDeclareTypeInfo(panda::pandasm::Program *prog,
147     const extractor::TypeRecorder *recorder, const M &map, AnnotationData &funcTypeAnnotation)
148 {
149     std::string symbolTypeStr;
150     if constexpr (isExport) {
151         symbolTypeStr = TypeExtractorEmitter::EXPORTED_SYMBOL_TYPES;
152     } else {
153         symbolTypeStr = TypeExtractorEmitter::DECLARED_SYMBOL_TYPES;
154     }
155 
156     std::vector<Literal> typedSymbols;
157     typedSymbols.reserve(map.size() * 4U);  // Expand to 4 pieces of information
158     for (const auto &t : map) {
159         Literal symbolTag;
160         Literal symbolValue;
161         symbolTag.tag_ = panda::panda_file::LiteralTag::TAGVALUE;
162         symbolTag.value_ = static_cast<uint8_t>(panda::panda_file::LiteralTag::STRING);
163         symbolValue.tag_ = panda::panda_file::LiteralTag::STRING;
164         symbolValue.value_ = t.first;
165         typedSymbols.emplace_back(symbolTag);
166         typedSymbols.emplace_back(symbolValue);
167 
168         GenTypeInfo(recorder, t.second, typedSymbols);
169     }
170 
171     std::lock_guard<std::mutex> lock(pg_->Context()->GetEmitter()->GetEmitterLock());
172     std::string literalId = std::string(recorder->GetRecordName()) + "_" +
173         func_->name + "_" + std::to_string(literalId_--);
174     auto literalArrayInstance = panda::pandasm::LiteralArray(std::move(typedSymbols));
175     prog->literalarray_table.emplace(literalId, std::move(literalArrayInstance));
176 
177     AnnotationElement funcSymbolTypeElement(symbolTypeStr,
178         std::make_unique<ScalarValue>(ScalarValue::Create<ValueType::LITERALARRAY>(literalId)));
179     funcTypeAnnotation.AddElement(std::move(funcSymbolTypeElement));
180 }
181 
GenExportTypeInfo(panda::pandasm::Program * prog)182 void TypeExtractorEmitter::GenExportTypeInfo(panda::pandasm::Program *prog)
183 {
184     AnnotationData funcTypeAnnotation(TypeExtractorEmitter::TYPE_ANNOTATION);
185     GenImportOrDeclareTypeInfo<true>(prog, pg_->Context()->TypeRecorder(),
186         pg_->Context()->TypeRecorder()->ExportType(), funcTypeAnnotation);
187     func_->metadata->AddAnnotations({ funcTypeAnnotation });
188 }
189 
GenDeclareTypeInfo(panda::pandasm::Program * prog)190 void TypeExtractorEmitter::GenDeclareTypeInfo(panda::pandasm::Program *prog)
191 {
192     AnnotationData funcTypeAnnotation(TypeExtractorEmitter::TYPE_ANNOTATION);
193     GenImportOrDeclareTypeInfo<false>(prog, pg_->Context()->TypeRecorder(),
194         pg_->Context()->TypeRecorder()->DeclareType(), funcTypeAnnotation);
195     func_->metadata->AddAnnotations({ funcTypeAnnotation });
196 }
197 
GenTypeSummaryInfo(bool typeFlag,int64_t typeSummaryIndex,const std::string & recordName,Record & record)198 static void GenTypeSummaryInfo(bool typeFlag, int64_t typeSummaryIndex, const std::string &recordName, Record &record)
199 {
200     constexpr const auto LANG_EXT = panda::pandasm::extensions::Language::ECMASCRIPT;
201 
202     auto typeFlagField = Field(LANG_EXT);
203     typeFlagField.name = TypeExtractorEmitter::TYPE_FLAG;
204     typeFlagField.type = Type("u8", 0);
205     typeFlagField.metadata->SetValue(ScalarValue::Create<ValueType::U8>(static_cast<uint8_t>(typeFlag)));
206     record.field_list.emplace_back(std::move(typeFlagField));
207 
208     if (typeFlag) {
209         auto typeSummaryIndexField = Field(LANG_EXT);
210         typeSummaryIndexField.name = TypeExtractorEmitter::TYPE_SUMMARY;
211         typeSummaryIndexField.type = Type("u32", 0);
212         typeSummaryIndexField.metadata->SetValue(ScalarValue::Create<ValueType::LITERALARRAY>(
213             "" + recordName + "_" + std::to_string(typeSummaryIndex)));
214         record.field_list.emplace_back(std::move(typeSummaryIndexField));
215     }
216 }
217 
218 // static
GenTypeInfoRecord(panda::pandasm::Program * prog,bool typeFlag,int64_t typeSummaryIndex,const std::string & recordName)219 void TypeExtractorEmitter::GenTypeInfoRecord(panda::pandasm::Program *prog, bool typeFlag,
220     int64_t typeSummaryIndex, const std::string &recordName)
221 {
222     auto iter = prog->record_table.find(TypeExtractorEmitter::TYPE_INFO_RECORD);
223     ASSERT(iter != prog->record_table.end());
224     GenTypeSummaryInfo(typeFlag, typeSummaryIndex, recordName, iter->second);
225 }
226 
GenTypeInfoRecordForMergeABC(panda::pandasm::Program * prog,bool typeFlag,int64_t typeSummaryIndex,const std::string & recordName)227 void TypeExtractorEmitter::GenTypeInfoRecordForMergeABC(panda::pandasm::Program *prog, bool typeFlag,
228     int64_t typeSummaryIndex, const std::string &recordName)
229 {
230     auto iter = prog->record_table.find(recordName);
231     ASSERT(iter != prog->record_table.end());
232     GenTypeSummaryInfo(typeFlag, typeSummaryIndex, recordName, iter->second);
233 }
234 
GenTypeLiteralBuffers(panda::pandasm::Program * prog,const extractor::TypeRecorder * recorder)235 void TypeExtractorEmitter::GenTypeLiteralBuffers(panda::pandasm::Program *prog,
236                                                  const extractor::TypeRecorder *recorder)
237 {
238     ArenaVector<std::pair<int32_t, std::vector<Literal>>> literalBuffers(recorder->Allocator()->Adapter());
239     for (const auto *buff : recorder->BuffStorage()) {
240         Emitter::GenBufferLiterals(literalBuffers, buff);
241     }
242 
243     for (auto &[idx, buf] : literalBuffers) {
244         std::string literalId = std::string(recorder->GetRecordName()) + "_" + std::to_string(idx);
245         auto literalArrayInstance = panda::pandasm::LiteralArray(std::move(buf));
246         prog->literalarray_table.emplace(literalId, std::move(literalArrayInstance));
247     }
248 }
249 
250 }  // namespace panda::es2panda::compiler
251