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