1 /* 2 * Copyright (c) 2021-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 16 #ifndef ES2PANDA_COMPILER_CHECKER_ETS_WIDENING_CONVERTER_H 17 #define ES2PANDA_COMPILER_CHECKER_ETS_WIDENING_CONVERTER_H 18 19 #include "checker/ETSchecker.h" 20 #include "checker/ets/typeConverter.h" 21 22 namespace ark::es2panda::checker { 23 24 class WideningConverter : public TypeConverter { 25 public: WideningConverter(ETSChecker * checker,TypeRelation * relation,Type * target,Type * source)26 explicit WideningConverter(ETSChecker *checker, TypeRelation *relation, Type *target, Type *source) 27 : TypeConverter(checker, relation, target, source) 28 { 29 if (!Relation()->ApplyWidening()) { 30 return; 31 } 32 33 if (!Source()->HasTypeFlag(TypeFlag::CONSTANT)) { 34 ApplyGlobalWidening(); 35 } else { 36 ApplyConstWidening(); 37 } 38 } 39 40 private: 41 static constexpr TypeFlag WIDENABLE_TO_SHORT = TypeFlag::BYTE; 42 static constexpr TypeFlag WIDENABLE_TO_CHAR = TypeFlag::BYTE; 43 static constexpr TypeFlag WIDENABLE_TO_INT = TypeFlag::CHAR | TypeFlag::SHORT | WIDENABLE_TO_SHORT; 44 static constexpr TypeFlag WIDENABLE_TO_LONG = TypeFlag::INT | WIDENABLE_TO_INT; 45 static constexpr TypeFlag WIDENABLE_TO_FLOAT = TypeFlag::LONG | WIDENABLE_TO_LONG; 46 static constexpr TypeFlag WIDENABLE_TO_DOUBLE = TypeFlag::FLOAT | WIDENABLE_TO_FLOAT; 47 ApplyConstWidening()48 void ApplyConstWidening() 49 { 50 switch (ETSChecker::ETSChecker::ETSType(Target())) { 51 case TypeFlag::SHORT: { 52 ApplyWidening<ShortType>(WIDENABLE_TO_SHORT); 53 break; 54 } 55 case TypeFlag::CHAR: { 56 ApplyWidening<CharType>(WIDENABLE_TO_CHAR); 57 break; 58 } 59 case TypeFlag::INT: { 60 ApplyWidening<IntType>(WIDENABLE_TO_INT); 61 break; 62 } 63 case TypeFlag::LONG: { 64 ApplyWidening<LongType>(WIDENABLE_TO_LONG); 65 break; 66 } 67 case TypeFlag::FLOAT: { 68 ApplyWidening<FloatType>(WIDENABLE_TO_FLOAT); 69 break; 70 } 71 case TypeFlag::DOUBLE: { 72 ApplyWidening<DoubleType>(WIDENABLE_TO_DOUBLE); 73 break; 74 } 75 default: { 76 break; 77 } 78 } 79 } 80 ApplyGlobalWidening()81 void ApplyGlobalWidening() 82 { 83 switch (ETSChecker::ETSChecker::ETSType(Target())) { 84 case TypeFlag::CHAR: { 85 ApplyGlobalWidening(WIDENABLE_TO_CHAR); 86 break; 87 } 88 case TypeFlag::SHORT: { 89 ApplyGlobalWidening(WIDENABLE_TO_SHORT); 90 break; 91 } 92 case TypeFlag::INT: { 93 ApplyGlobalWidening(WIDENABLE_TO_INT); 94 break; 95 } 96 case TypeFlag::LONG: { 97 ApplyGlobalWidening(WIDENABLE_TO_LONG); 98 break; 99 } 100 case TypeFlag::FLOAT: { 101 ApplyGlobalWidening(WIDENABLE_TO_FLOAT); 102 break; 103 } 104 case TypeFlag::DOUBLE: { 105 ApplyGlobalWidening(WIDENABLE_TO_DOUBLE); 106 break; 107 } 108 default: { 109 break; 110 } 111 } 112 } 113 ApplyGlobalWidening(TypeFlag flag)114 void ApplyGlobalWidening(TypeFlag flag) 115 { 116 if (!Source()->HasTypeFlag(flag)) { 117 return; 118 } 119 120 if (!Relation()->OnlyCheckWidening()) { 121 ES2PANDA_ASSERT(Relation()->GetNode()); 122 switch (ETSChecker::ETSChecker::ETSType(Source())) { 123 case TypeFlag::BYTE: { 124 Relation()->GetNode()->SetTsType(Checker()->GlobalByteType()); 125 break; 126 } 127 case TypeFlag::SHORT: { 128 Relation()->GetNode()->SetTsType(Checker()->GlobalShortType()); 129 break; 130 } 131 case TypeFlag::CHAR: { 132 Relation()->GetNode()->SetTsType(Checker()->GlobalCharType()); 133 break; 134 } 135 case TypeFlag::INT: { 136 Relation()->GetNode()->SetTsType(Checker()->GlobalIntType()); 137 break; 138 } 139 case TypeFlag::LONG: { 140 Relation()->GetNode()->SetTsType(Checker()->GlobalLongType()); 141 break; 142 } 143 case TypeFlag::FLOAT: { 144 Relation()->GetNode()->SetTsType(Checker()->GlobalFloatType()); 145 break; 146 } 147 case TypeFlag::DOUBLE: { 148 Relation()->GetNode()->SetTsType(Checker()->GlobalDoubleType()); 149 break; 150 } 151 default: { 152 return; 153 } 154 } 155 } 156 157 Relation()->Result(true); 158 } 159 160 template <typename TargetType> ApplyWidening(TypeFlag flag)161 void ApplyWidening(TypeFlag flag) 162 { 163 if (!Source()->HasTypeFlag(flag)) { 164 return; 165 } 166 167 switch (ETSChecker::ETSChecker::ETSType(Source())) { 168 case TypeFlag::BYTE: { 169 ApplyWidening<TargetType, ByteType>(); 170 break; 171 } 172 case TypeFlag::CHAR: { 173 ApplyWidening<TargetType, CharType>(); 174 break; 175 } 176 case TypeFlag::SHORT: { 177 ApplyWidening<TargetType, ShortType>(); 178 break; 179 } 180 case TypeFlag::INT: { 181 ApplyWidening<TargetType, IntType>(); 182 break; 183 } 184 case TypeFlag::LONG: { 185 ApplyWidening<TargetType, LongType>(); 186 break; 187 } 188 case TypeFlag::FLOAT: { 189 ApplyWidening<TargetType, FloatType>(); 190 break; 191 } 192 case TypeFlag::DOUBLE: { 193 ApplyWidening<TargetType, DoubleType>(); 194 break; 195 } 196 default: { 197 return; 198 } 199 } 200 Relation()->Result(true); 201 } 202 203 template <typename TargetType, typename SourceType> ApplyWidening()204 void ApplyWidening() 205 { 206 using SType = typename SourceType::UType; 207 using TType = typename TargetType::UType; 208 SType value = reinterpret_cast<SourceType *>(Source())->GetValue(); 209 210 if (!Relation()->OnlyCheckWidening()) { 211 ES2PANDA_ASSERT(Relation()->GetNode()); 212 Relation()->GetNode()->SetTsType(Checker()->ProgramAllocator()->New<TargetType>(static_cast<TType>(value))); 213 } 214 } 215 }; 216 } // namespace ark::es2panda::checker 217 218 #endif 219