• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2022-2025 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 #ifndef PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_ETS_INTEROP_RUNTIME_INTERFACE_INL_H
16 #define PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_ETS_INTEROP_RUNTIME_INTERFACE_INL_H
17 
18 // CC-OFFNXT(G.NAM.01) false positive
GetInfoForInteropConvert(panda_file::Type::TypeId typeId)19 static std::pair<IntrinsicId, compiler::DataType::Type> GetInfoForInteropConvert(panda_file::Type::TypeId typeId)
20 {
21     switch (typeId) {
22         case panda_file::Type::TypeId::VOID:
23             return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_VOID_TO_LOCAL, compiler::DataType::NO_TYPE};
24         case panda_file::Type::TypeId::U1:
25             return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_U1_TO_LOCAL, compiler::DataType::BOOL};
26         case panda_file::Type::TypeId::I8:
27             return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_I8_TO_LOCAL, compiler::DataType::INT8};
28         case panda_file::Type::TypeId::U8:
29             return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_U8_TO_LOCAL, compiler::DataType::UINT8};
30         case panda_file::Type::TypeId::I16:
31             return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_I16_TO_LOCAL, compiler::DataType::INT16};
32         case panda_file::Type::TypeId::U16:
33             return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_U16_TO_LOCAL, compiler::DataType::UINT16};
34         case panda_file::Type::TypeId::I32:
35             return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_I32_TO_LOCAL, compiler::DataType::INT32};
36         case panda_file::Type::TypeId::U32:
37             return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_U32_TO_LOCAL, compiler::DataType::UINT32};
38         case panda_file::Type::TypeId::I64:
39             return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_I64_TO_LOCAL, compiler::DataType::INT64};
40         case panda_file::Type::TypeId::U64:
41             return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_U64_TO_LOCAL, compiler::DataType::UINT64};
42         case panda_file::Type::TypeId::F32:
43             return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_F32_TO_LOCAL, compiler::DataType::FLOAT32};
44         case panda_file::Type::TypeId::F64:
45             return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_F64_TO_LOCAL, compiler::DataType::FLOAT64};
46         case panda_file::Type::TypeId::REFERENCE:
47             return {IntrinsicId::INTRINSIC_COMPILER_CONVERT_REF_TYPE_TO_LOCAL, compiler::DataType::REFERENCE};
48         default: {
49             UNREACHABLE();
50         }
51     }
52 }
53 
GetInfoForInteropCallArgsConversion(MethodPtr methodPtr,uint32_t skipArgs,ArenaVector<std::pair<IntrinsicId,compiler::DataType::Type>> * intrinsics)54 void GetInfoForInteropCallArgsConversion(
55     MethodPtr methodPtr, uint32_t skipArgs,
56     // CC-OFFNXT(G.NAM.01) false positive
57     ArenaVector<std::pair<IntrinsicId, compiler::DataType::Type>> *intrinsics) const override
58 {
59     auto method = MethodCast(methodPtr);
60     uint32_t numArgs = method->GetNumArgs() - skipArgs;
61     panda_file::ShortyIterator it(method->GetShorty());
62     for (uint32_t i = 0; i < 1U + skipArgs; i++) {  // 1 for return value
63         it.IncrementWithoutCheck();
64     }
65     for (uint32_t argIdx = 0; argIdx < numArgs; ++argIdx, it.IncrementWithoutCheck()) {
66         auto type = *it;
67         intrinsics->push_back(GetInfoForInteropConvert(type.GetId()));
68     }
69 }
70 
GetInteropRefReturnValueConvertIntrinsic(Method * method)71 compiler::RuntimeInterface::IntrinsicId GetInteropRefReturnValueConvertIntrinsic(Method *method) const
72 {
73     auto vm = reinterpret_cast<PandaEtsVM *>(Thread::GetCurrent()->GetVM());
74     auto classLinker = vm->GetClassLinker();
75     auto klass = GetClass(method, GetMethodReturnTypeId(method));
76     const char *jsValueDesc = panda_file_items::class_descriptors::JS_VALUE.data();
77     const char *stringDesc = panda_file_items::class_descriptors::STRING.data();
78     auto *jsValueClass = classLinker->GetClass(jsValueDesc);
79     auto *stringClass = classLinker->GetClass(stringDesc);
80     ASSERT(jsValueClass != nullptr);
81     ASSERT(stringClass != nullptr);
82 
83     // start fastpath
84     if (klass == jsValueClass->GetRuntimeClass()) {
85         return IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_JS_VALUE;
86     }
87     if (klass == stringClass->GetRuntimeClass()) {
88         return IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_STRING;
89     }
90     return IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_REF_TYPE;
91 }
92 
93 // CC-OFFNXT(G.FMT.07) project code style
94 std::optional<std::pair<compiler::RuntimeInterface::IntrinsicId, compiler::DataType::Type>>
GetInfoForInteropCallRetValueConversion(MethodPtr methodPtr)95 GetInfoForInteropCallRetValueConversion(MethodPtr methodPtr) const override
96 {
97     auto method = MethodCast(methodPtr);
98     auto type = method->GetReturnType();
99     switch (type.GetId()) {
100         case panda_file::Type::TypeId::VOID:
101             return {};
102         case panda_file::Type::TypeId::U1:
103             return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_U1, compiler::DataType::BOOL}};
104         case panda_file::Type::TypeId::I8:
105             return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_I8, compiler::DataType::INT8}};
106         case panda_file::Type::TypeId::U8:
107             return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_U8, compiler::DataType::UINT8}};
108         case panda_file::Type::TypeId::I16:
109             return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_I16, compiler::DataType::INT16}};
110         case panda_file::Type::TypeId::U16:
111             return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_U16, compiler::DataType::UINT16}};
112         case panda_file::Type::TypeId::I32:
113             return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_I32, compiler::DataType::INT32}};
114         case panda_file::Type::TypeId::U32:
115             return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_U32, compiler::DataType::UINT32}};
116         case panda_file::Type::TypeId::I64:
117             return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_I64, compiler::DataType::INT64}};
118         case panda_file::Type::TypeId::U64:
119             return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_U64, compiler::DataType::UINT64}};
120         case panda_file::Type::TypeId::F32:
121             return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_F32, compiler::DataType::FLOAT32}};
122         case panda_file::Type::TypeId::F64:
123             return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_F64, compiler::DataType::FLOAT64}};
124         case panda_file::Type::TypeId::REFERENCE: {
125             return {{GetInteropRefReturnValueConvertIntrinsic(method), compiler::DataType::REFERENCE}};
126         }
127         default: {
128             UNREACHABLE();
129         }
130     }
131     return {};
132 }
133 
GetInteropConstantPoolOffsetField(ClassPtr klass)134 FieldPtr GetInteropConstantPoolOffsetField(ClassPtr klass) const override
135 {
136     auto fields = ClassCast(klass)->GetStaticFields();
137     ASSERT(fields.Size() == 1);
138     return &fields[0];
139 }
140 
141 // returns index of the first element in annotation array having the same value as element `index`
GetAnnotationElementUniqueIndex(ClassPtr klass,const char * annotation,uint32_t index)142 uint32_t GetAnnotationElementUniqueIndex(ClassPtr klass, const char *annotation, uint32_t index) override
143 {
144     auto [it, inserted] = annotationOffsets_.try_emplace(klass);
145     if (!inserted) {
146         return it->second[index];
147     }
148     auto pf = ClassCast(klass)->GetPandaFile();
149     panda_file::ClassDataAccessor cda(*pf, ClassCast(klass)->GetFileId());
150 
151     [[maybe_unused]] auto annotationFound =
152         cda.EnumerateAnnotation(annotation, [pf, &indices = it->second](panda_file::AnnotationDataAccessor &ada) {
153             for (uint32_t i = 0; i < ada.GetCount(); i++) {
154                 auto adae = ada.GetElement(i);
155                 auto *elemName = pf->GetStringData(adae.GetNameId()).data;
156                 if (!utf::IsEqual(utf::CStringAsMutf8("value"), elemName)) {
157                     continue;
158                 }
159                 auto arr = adae.GetArrayValue();
160                 indices.resize(arr.GetCount());
161                 std::unordered_map<uint32_t, uint32_t> firstIndexByOffset;
162                 for (uint32_t strIdx = 0; strIdx < indices.size(); strIdx++) {
163                     auto strOffset = arr.Get<uint32_t>(strIdx);
164                     indices[strIdx] = firstIndexByOffset.try_emplace(strOffset, strIdx).first->second;
165                 }
166                 return true;
167             }
168             UNREACHABLE();
169         });
170     ASSERT(annotationFound.has_value());
171     return it->second[index];
172 }
173 
174 private:
175 std::unordered_map<ClassPtr, std::vector<uint32_t>> annotationOffsets_;
176 
177 #endif  // PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_ETS_INTEROP_RUNTIME_INTERFACE_INL_H
178