• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 #ifndef ECMASCRIPT_JSPANDAFILE_TYPE_LITERAL_EXTRACTOR_H
17 #define ECMASCRIPT_JSPANDAFILE_TYPE_LITERAL_EXTRACTOR_H
18 
19 #include "ecmascript/jspandafile/js_pandafile.h"
20 
21 namespace panda::ecmascript {
22 class TypeLiteralExtractor {
23 using TypeLiteralValue = std::variant<uint32_t, CString>;
24 
25 public:
26     explicit TypeLiteralExtractor(const JSPandaFile *jsPandaFile, const uint32_t typeOffset);
27     ~TypeLiteralExtractor() = default;
28     NO_COPY_SEMANTIC(TypeLiteralExtractor);
29     NO_MOVE_SEMANTIC(TypeLiteralExtractor);
30 
IsVaildTypeLiteral()31     inline bool IsVaildTypeLiteral() const
32     {
33         return !array_.empty();
34     }
35 
GetTypeKind()36     inline TSTypeKind GetTypeKind() const
37     {
38         return kind_;
39     }
40 
IsGenerics()41     inline bool IsGenerics() const
42     {
43         return isGenerics_;
44     }
45 
GetIntValue(const uint32_t index)46     inline uint32_t GetIntValue(const uint32_t index) const
47     {
48         ASSERT(index < array_.size());
49         auto t = array_[index];
50         ASSERT(std::holds_alternative<uint32_t>(t));
51         return std::get<uint32_t>(t);
52     }
53 
GetStringValue(const uint32_t index)54     inline const CString &GetStringValue(const uint32_t index) const
55     {
56         ASSERT(index < array_.size());
57         const auto &t = array_[index];
58         ASSERT(std::holds_alternative<CString>(t));
59         return std::get<CString>(t);
60     }
61 
GetTypeOffset()62     inline uint32_t GetTypeOffset() const
63     {
64         return typeOffset_;
65     }
66 
67     template <class Callback>
EnumerateElements(const uint32_t numIndex,const Callback & callback)68     void EnumerateElements(const uint32_t numIndex, const Callback &callback)
69     {
70         ASSERT(numIndex < array_.size());
71         uint32_t length = std::get<uint32_t>(array_[numIndex]);
72         ASSERT(numIndex + length < array_.size());
73         for (uint32_t i = 1; i <= length; i++) {
74             uint32_t value = GetIntValue(numIndex + i);
75             callback(value);
76         }
77     }
78 
79     template <class Callback>
EnumerateTypesWithIntKey(const uint32_t numIndex,const Callback & callback)80     void EnumerateTypesWithIntKey(const uint32_t numIndex, const Callback &callback)
81     {
82         ASSERT(numIndex < array_.size());
83         const uint32_t gap = 2;
84         uint32_t length = std::get<uint32_t>(array_[numIndex]);
85         ASSERT(numIndex + length * gap < array_.size());
86         for (uint32_t i = 0; i < length; i++) {
87             uint32_t keyIndex = numIndex + i * gap + KEY_OFFSET;
88             uint32_t valueIndex = numIndex + i * gap + VALUE_OFFSET;
89             uint32_t key = GetIntValue(keyIndex);
90             uint32_t value = GetIntValue(valueIndex);
91             callback(key, value);
92         }
93     }
94 
95     template <class Callback>
EnumerateProperties(const uint32_t numIndex,const uint32_t gap,const Callback & callback)96     void EnumerateProperties(const uint32_t numIndex, const uint32_t gap, const Callback &callback)
97     {
98         ASSERT(numIndex < array_.size());
99         ASSERT(gap >= VALUE_OFFSET);
100         uint32_t length = std::get<uint32_t>(array_[numIndex]);
101         ASSERT(numIndex + length * gap < array_.size());
102         for (uint32_t i = 0; i < length; i++) {
103             uint32_t keyIndex = numIndex + i * gap + KEY_OFFSET;
104             uint32_t valueIndex = numIndex + i * gap + VALUE_OFFSET;
105             const CString &key = GetStringValue(keyIndex);
106             uint32_t value = GetIntValue(valueIndex);
107             callback(key, value);
108         }
109     }
110 
111     void Print() const;
112 
113 private:
114     static constexpr uint32_t KEY_OFFSET = 1;
115     static constexpr uint32_t VALUE_OFFSET = 2;
116 
IsVaildKind(const uint32_t kindValue)117     inline bool IsVaildKind(const uint32_t kindValue) const
118     {
119         return (static_cast<uint32_t>(TSTypeKind::TYPEKIND_FIRST) <= kindValue) &&
120                (kindValue <= static_cast<uint32_t>(TSTypeKind::TYPEKIND_LAST));
121     }
122 
123     void ProcessTypeLiteral(const JSPandaFile *jsPandaFile, const uint32_t typeOffset);
124     std::string PrintTypeKind(TSTypeKind typeKind) const;
125 
126     std::vector<TypeLiteralValue> array_;
127     uint32_t typeOffset_ { 0 };
128     TSTypeKind kind_ { TSTypeKind::UNKNOWN };
129     bool isGenerics_ { false };
130 };
131 
132 class TypeSummaryExtractor {
133 public:
134     explicit TypeSummaryExtractor(const JSPandaFile *jsPandaFile, const CString &recordName);
135     ~TypeSummaryExtractor() = default;
136     NO_COPY_SEMANTIC(TypeSummaryExtractor);
137     NO_MOVE_SEMANTIC(TypeSummaryExtractor);
138 
139     template <class Callback>
EnumerateTypeOffsets(const uint32_t lastIndex,const Callback & callback)140     void EnumerateTypeOffsets(const uint32_t lastIndex, const Callback &callback)
141     {
142         ASSERT(lastIndex < typeOffsets_.size());
143         for (uint32_t i = 0; i <= lastIndex; i++) {
144             callback(typeOffsets_[i]);
145         }
146     }
147 
GetNumOfTypes()148     inline uint32_t GetNumOfTypes() const
149     {
150         return numOfTypes_;
151     }
152 
153     void Print() const;
154 
155 private:
156     void ProcessTypeSummary(const JSPandaFile *jsPandaFile, const uint32_t summaryOffset);
157 
158     const JSPandaFile *jsPandaFile_ {nullptr};
159     std::vector<uint32_t> typeOffsets_ {};
160     std::vector<CString> reDirects_ {};
161     uint32_t numOfTypes_ { 0 };
162     uint32_t numOfRedirects_ { 0 };
163 };
164 
165 class TypeAnnotationExtractor {
166 using LiteralTag = panda_file::LiteralTag;
167 
168 public:
169     explicit TypeAnnotationExtractor(const JSPandaFile *jsPandaFile, const uint32_t methodOffset);
170     ~TypeAnnotationExtractor() = default;
171     NO_COPY_SEMANTIC(TypeAnnotationExtractor);
172     NO_MOVE_SEMANTIC(TypeAnnotationExtractor);
173 
174     template <class Callback>
EnumerateInstsAndTypes(const Callback & callback)175     void EnumerateInstsAndTypes(const Callback &callback)
176     {
177         ASSERT(bcOffsets_.size() == typeIds_.size());
178         uint32_t length = bcOffsets_.size();
179         for (uint32_t i = 0; i < length; i++) {
180             callback(bcOffsets_[i], typeIds_[i]);
181         }
182     }
183 
GetMethodTypeOffset()184     uint32_t GetMethodTypeOffset() const
185     {
186         return methodTypeOffset_;
187     }
188 
IsNamespace()189     bool IsNamespace() const
190     {
191         return isNamespace_;
192     }
193 
194     void Print() const;
195 
196 private:
197     static constexpr const char *TYPE_ANNO_ELEMENT_NAME = "_TypeOfInstruction";
198     static constexpr int METHOD_ANNOTATION_FUNCTION_TYPE_OFFSET = -1;
199     static constexpr int METHOD_ANNOTATION_NAMESPACE = 255;
200     static constexpr int METHOD_ANNOTATION_ENUM = 254;
201 
202     void ProcessTypeAnnotation(const JSPandaFile *jsPandaFile, const uint32_t methodOffset);
203     void CollectTSMethodKind();
204     std::string PrintTag(LiteralTag tag) const;
205 
206     uint32_t methodTypeOffset_ {0};
207     std::vector<int32_t> bcOffsets_ {};
208     std::vector<uint32_t> typeIds_ {};
209     std::vector<LiteralTag> tags_ {};
210     bool isNamespace_ {false};
211 };
212 
213 class ExportTypeTableExtractor {
214 public:
215     explicit ExportTypeTableExtractor(const JSPandaFile *jsPandaFile, const CString &recordName, bool isBuiltinTable);
216     ~ExportTypeTableExtractor() = default;
217     NO_COPY_SEMANTIC(ExportTypeTableExtractor);
218     NO_MOVE_SEMANTIC(ExportTypeTableExtractor);
219 
GetLength()220     inline uint32_t GetLength() const
221     {
222         ASSERT(exportVars_.size() == typeIds_.size());
223         return exportVars_.size() + typeIds_.size();
224     }
225 
226     template <class Callback>
EnumerateModuleTypes(const Callback & callback)227     void EnumerateModuleTypes(const Callback &callback)
228     {
229         ASSERT(exportVars_.size() == typeIds_.size());
230         uint32_t length = exportVars_.size();
231         for (uint32_t i = 0; i < length; i++) {
232             callback(exportVars_[i], typeIds_[i]);
233         }
234     }
235 
236     void Print() const;
237 
238 private:
239     static constexpr const char *DECLARED_SYMBOL_TYPES = "declaredSymbolTypes";
240     static constexpr const char *EXPORTED_SYMBOL_TYPES = "exportedSymbolTypes";
241 
242     void ProcessExportTable(const JSPandaFile *jsPandaFile, const CString &recordName, bool isBuiltinTable);
243 
244     std::vector<CString> exportVars_ {};
245     std::vector<uint32_t> typeIds_ {};
246 };
247 }  // namespace panda::ecmascript
248 #endif  // ECMASCRIPT_JSPANDAFILE_TYPE_LITERAL_EXTRACTOR_H
249