1 /*
2 * Copyright (c) 2022-2024 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 // start fastpath
77 if (klass == classLinker->GetClass(panda_file_items::class_descriptors::JS_VALUE.data())->GetRuntimeClass()) {
78 return IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_JS_VALUE;
79 }
80 if (klass == classLinker->GetClass(panda_file_items::class_descriptors::STRING.data())->GetRuntimeClass()) {
81 return IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_STRING;
82 }
83 return IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_REF_TYPE;
84 }
85
86 // CC-OFFNXT(G.FMT.07) project code style
87 std::optional<std::pair<compiler::RuntimeInterface::IntrinsicId, compiler::DataType::Type>>
GetInfoForInteropCallRetValueConversion(MethodPtr methodPtr)88 GetInfoForInteropCallRetValueConversion(MethodPtr methodPtr) const override
89 {
90 auto method = MethodCast(methodPtr);
91 auto type = method->GetReturnType();
92 switch (type.GetId()) {
93 case panda_file::Type::TypeId::VOID:
94 return {};
95 case panda_file::Type::TypeId::U1:
96 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_U1, compiler::DataType::BOOL}};
97 case panda_file::Type::TypeId::I8:
98 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_I8, compiler::DataType::INT8}};
99 case panda_file::Type::TypeId::U8:
100 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_U8, compiler::DataType::UINT8}};
101 case panda_file::Type::TypeId::I16:
102 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_I16, compiler::DataType::INT16}};
103 case panda_file::Type::TypeId::U16:
104 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_U16, compiler::DataType::UINT16}};
105 case panda_file::Type::TypeId::I32:
106 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_I32, compiler::DataType::INT32}};
107 case panda_file::Type::TypeId::U32:
108 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_U32, compiler::DataType::UINT32}};
109 case panda_file::Type::TypeId::I64:
110 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_I64, compiler::DataType::INT64}};
111 case panda_file::Type::TypeId::U64:
112 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_U64, compiler::DataType::UINT64}};
113 case panda_file::Type::TypeId::F32:
114 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_F32, compiler::DataType::FLOAT32}};
115 case panda_file::Type::TypeId::F64:
116 return {{IntrinsicId::INTRINSIC_COMPILER_CONVERT_LOCAL_TO_F64, compiler::DataType::FLOAT64}};
117 case panda_file::Type::TypeId::REFERENCE: {
118 return {{GetInteropRefReturnValueConvertIntrinsic(method), compiler::DataType::REFERENCE}};
119 }
120 default: {
121 UNREACHABLE();
122 }
123 }
124 return {};
125 }
126
GetInteropConstantPoolOffsetField(ClassPtr klass)127 FieldPtr GetInteropConstantPoolOffsetField(ClassPtr klass) const override
128 {
129 auto fields = ClassCast(klass)->GetStaticFields();
130 ASSERT(fields.Size() == 1);
131 return &fields[0];
132 }
133
134 // 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)135 uint32_t GetAnnotationElementUniqueIndex(ClassPtr klass, const char *annotation, uint32_t index) override
136 {
137 auto [it, inserted] = annotationOffsets_.try_emplace(klass);
138 if (!inserted) {
139 return it->second[index];
140 }
141 auto pf = ClassCast(klass)->GetPandaFile();
142 panda_file::ClassDataAccessor cda(*pf, ClassCast(klass)->GetFileId());
143
144 [[maybe_unused]] auto annotationFound =
145 cda.EnumerateAnnotation(annotation, [pf, &indices = it->second](panda_file::AnnotationDataAccessor &ada) {
146 for (uint32_t i = 0; i < ada.GetCount(); i++) {
147 auto adae = ada.GetElement(i);
148 auto *elemName = pf->GetStringData(adae.GetNameId()).data;
149 if (!utf::IsEqual(utf::CStringAsMutf8("value"), elemName)) {
150 continue;
151 }
152 auto arr = adae.GetArrayValue();
153 indices.resize(arr.GetCount());
154 std::unordered_map<uint32_t, uint32_t> firstIndexByOffset;
155 for (uint32_t strIdx = 0; strIdx < indices.size(); strIdx++) {
156 auto strOffset = arr.Get<uint32_t>(strIdx);
157 indices[strIdx] = firstIndexByOffset.try_emplace(strOffset, strIdx).first->second;
158 }
159 return true;
160 }
161 UNREACHABLE();
162 });
163 ASSERT(annotationFound.has_value());
164 return it->second[index];
165 }
166
167 private:
168 std::unordered_map<ClassPtr, std::vector<uint32_t>> annotationOffsets_;
169
170 #endif // PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_ETS_INTEROP_RUNTIME_INTERFACE_INL_H
171