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