• 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 AnnotationData = panda::pandasm::AnnotationData;
26 using AnnotationElement = panda::pandasm::AnnotationElement;
27 using ArrayValue = panda::pandasm::ArrayValue;
28 using Field = panda::pandasm::Field;
29 using ScalarValue = panda::pandasm::ScalarValue;
30 using ValueType = panda::pandasm::Value::Type;
31 using Type = panda::pandasm::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     GenFunctionTypeInfo();
36     if (func->name == binder::Binder::MAIN_FUNC_NAME) {
37         if (pg_->Context()->TypeRecorder()->ExportType().size() > 0U) {
38             GenExportTypeInfo();
39         }
40         if (pg_->Context()->TypeRecorder()->DeclareType().size() > 0U) {
41             GenDeclareTypeInfo();
42         }
43     }
44 }
45 
GenFunctionTypeInfo() const46 void TypeExtractorEmitter::GenFunctionTypeInfo() const
47 {
48     std::vector<ScalarValue> typedInsns;
49     typedInsns.reserve(pg_->TypedInsns().size());
50     size_t index = 0U;
51     for (const auto *ins : pg_->Insns()) {
52         auto t = pg_->TypedInsns().find(ins);
53         if (t != pg_->TypedInsns().end()) {
54             const auto &insn = func_->ins[index];
55             int64_t typeIndex = t->second;
56             int32_t orderIndex = index;
57             if (typeIndex < extractor::TypeRecorder::PRIMITIVETYPE_ANY) {
58                 // Decode type and order index for params
59                 typeIndex = -(typeIndex + 1);
60                 orderIndex = static_cast<int32_t>(func_->regs_num) - static_cast<int32_t>(insn.regs[1]) - 1;
61             }
62             if (typeIndex > extractor::TypeRecorder::PRIMITIVETYPE_ANY) {
63                 ScalarValue insnOrder(ScalarValue::Create<ValueType::I32>(orderIndex));
64                 typedInsns.emplace_back(std::move(insnOrder));
65                 ScalarValue insnType(ScalarValue::Create<ValueType::I32>(typeIndex));
66                 typedInsns.emplace_back(std::move(insnType));
67 #ifndef NDEBUG
68                 std::cout << "[LOG]" << func_->name << ": " << insn.ToString("", true, func_->regs_num) << " | "
69                     << orderIndex << " | " << typeIndex << std::endl;
70 #endif
71             }
72         }
73         index++;
74     }
75 
76     AnnotationData funcTypeAnnotation(TypeExtractorEmitter::TYPE_ANNOTATION);
77     AnnotationElement funcTypeAnnotationElement(TypeExtractorEmitter::TYPE_INSTRUCTION,
78         std::make_unique<ArrayValue>(ArrayValue(ValueType::U32, typedInsns)));
79     funcTypeAnnotation.AddElement(std::move(funcTypeAnnotationElement));
80     func_->metadata->AddAnnotations({ funcTypeAnnotation });
81 }
82 
83 template <bool isExport, typename M, typename F>
GenTypeInfo(const M & map,F & funcTypeAnnotation)84 static void GenTypeInfo(const M &map, F &funcTypeAnnotation)
85 {
86     std::string symbolStr;
87     std::string symbolTypeStr;
88     if constexpr (isExport) {
89         symbolStr = TypeExtractorEmitter::EXPORTED_SYMBOLS;
90         symbolTypeStr = TypeExtractorEmitter::EXPORTED_SYMBOL_TYPES;
91     } else {
92         symbolStr = TypeExtractorEmitter::DECLARED_SYMBOLS;
93         symbolTypeStr = TypeExtractorEmitter::DECLARED_SYMBOL_TYPES;
94     }
95 
96     std::vector<ScalarValue> symbolElements;
97     std::vector<ScalarValue> symbolTypeElements;
98     for (const auto &t : map) {
99         ScalarValue symbol(ScalarValue::Create<ValueType::STRING>(t.first));
100         symbolElements.emplace_back(std::move(symbol));
101         ScalarValue symbolType(ScalarValue::Create<ValueType::U32>(t.second));
102         symbolTypeElements.emplace_back(std::move(symbolType));
103     }
104 
105     AnnotationElement funcSymbolsElements(symbolStr,
106         std::make_unique<ArrayValue>(ArrayValue(ValueType::STRING, symbolElements)));
107     AnnotationElement funcSymbolTypeElement(symbolTypeStr,
108         std::make_unique<ArrayValue>(ArrayValue(ValueType::U32, symbolTypeElements)));
109 
110     funcTypeAnnotation.AddElement(std::move(funcSymbolsElements));
111     funcTypeAnnotation.AddElement(std::move(funcSymbolTypeElement));
112 }
113 
GenExportTypeInfo() const114 void TypeExtractorEmitter::GenExportTypeInfo() const
115 {
116     AnnotationData funcTypeAnnotation(TypeExtractorEmitter::TYPE_ANNOTATION);
117     GenTypeInfo<true>(pg_->Context()->TypeRecorder()->ExportType(), funcTypeAnnotation);
118     func_->metadata->AddAnnotations({ funcTypeAnnotation });
119 }
120 
GenDeclareTypeInfo() const121 void TypeExtractorEmitter::GenDeclareTypeInfo() const
122 {
123     AnnotationData funcTypeAnnotation(TypeExtractorEmitter::TYPE_ANNOTATION);
124     GenTypeInfo<false>(pg_->Context()->TypeRecorder()->DeclareType(), funcTypeAnnotation);
125     func_->metadata->AddAnnotations({ funcTypeAnnotation });
126 }
127 
128 // static
GenTypeInfoRecord(panda::pandasm::Program * prog,bool typeFlag,int64_t typeSummaryIndex)129 void TypeExtractorEmitter::GenTypeInfoRecord(panda::pandasm::Program *prog, bool typeFlag, int64_t typeSummaryIndex)
130 {
131     constexpr const auto LANG_EXT = panda::pandasm::extensions::Language::ECMASCRIPT;
132     auto &typeInfoRecord = prog->record_table.find(TypeExtractorEmitter::TYPE_INFO_RECORD)->second;
133 
134     auto typeFlagField = Field(LANG_EXT);
135     typeFlagField.name = TypeExtractorEmitter::TYPE_FLAG;
136     typeFlagField.type = Type("u8", 0);
137     typeFlagField.metadata->SetValue(ScalarValue::Create<ValueType::U8>(static_cast<uint8_t>(typeFlag)));
138     typeInfoRecord.field_list.emplace_back(std::move(typeFlagField));
139 
140     auto typeSummaryIndexField = Field(LANG_EXT);
141     typeSummaryIndexField.name = TypeExtractorEmitter::TYPE_SUMMARY;
142     typeSummaryIndexField.type = Type("u32", 0);
143     typeSummaryIndexField.metadata->SetValue(ScalarValue::Create<ValueType::U32>(
144         static_cast<uint32_t>(typeSummaryIndex)));
145     typeInfoRecord.field_list.emplace_back(std::move(typeSummaryIndexField));
146 }
147 
GenTypeLiteralBuffers(panda::pandasm::Program * prog,const extractor::TypeRecorder * recorder)148 void TypeExtractorEmitter::GenTypeLiteralBuffers(panda::pandasm::Program *prog,
149                                                  const extractor::TypeRecorder *recorder)
150 {
151     ArenaVector<std::pair<int32_t, std::vector<Literal>>> literalBuffers(recorder->Allocator()->Adapter());
152     for (const auto *buff : recorder->BuffStorage()) {
153         Emitter::GenBufferLiterals(literalBuffers, buff);
154     }
155 
156     for (auto &[idx, buf] : literalBuffers) {
157         auto literalArrayInstance = panda::pandasm::LiteralArray(std::move(buf));
158         prog->literalarray_table.emplace(std::to_string(idx), std::move(literalArrayInstance));
159     }
160 }
161 
162 }  // namespace panda::es2panda::compiler
163