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