1 /* 2 * Copyright (c) 2021 - 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 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 panda::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::SHORT: { 74 ApplyGlobalWidening(TypeFlag::WIDENABLE_TO_SHORT); 75 break; 76 } 77 case TypeFlag::INT: { 78 ApplyGlobalWidening(TypeFlag::WIDENABLE_TO_INT); 79 break; 80 } 81 case TypeFlag::LONG: { 82 ApplyGlobalWidening(TypeFlag::WIDENABLE_TO_LONG); 83 break; 84 } 85 case TypeFlag::FLOAT: { 86 ApplyGlobalWidening(TypeFlag::WIDENABLE_TO_FLOAT); 87 break; 88 } 89 case TypeFlag::DOUBLE: { 90 ApplyGlobalWidening(TypeFlag::WIDENABLE_TO_DOUBLE); 91 break; 92 } 93 default: { 94 break; 95 } 96 } 97 } 98 ApplyGlobalWidening(TypeFlag flag)99 void ApplyGlobalWidening(TypeFlag flag) 100 { 101 if (!Source()->HasTypeFlag(flag)) { 102 return; 103 } 104 105 if (!Relation()->OnlyCheckWidening()) { 106 ASSERT(Relation()->GetNode()); 107 switch (ETSChecker::ETSChecker::ETSType(Source())) { 108 case TypeFlag::BYTE: { 109 Relation()->GetNode()->SetTsType(Checker()->GlobalByteType()); 110 break; 111 } 112 case TypeFlag::SHORT: { 113 Relation()->GetNode()->SetTsType(Checker()->GlobalShortType()); 114 break; 115 } 116 case TypeFlag::CHAR: { 117 Relation()->GetNode()->SetTsType(Checker()->GlobalCharType()); 118 break; 119 } 120 case TypeFlag::INT: { 121 Relation()->GetNode()->SetTsType(Checker()->GlobalIntType()); 122 break; 123 } 124 case TypeFlag::LONG: { 125 Relation()->GetNode()->SetTsType(Checker()->GlobalLongType()); 126 break; 127 } 128 case TypeFlag::FLOAT: { 129 Relation()->GetNode()->SetTsType(Checker()->GlobalFloatType()); 130 break; 131 } 132 case TypeFlag::DOUBLE: { 133 Relation()->GetNode()->SetTsType(Checker()->GlobalDoubleType()); 134 break; 135 } 136 default: { 137 return; 138 } 139 } 140 } 141 142 Relation()->Result(true); 143 } 144 145 template <typename TargetType> ApplyWidening(TypeFlag flag)146 void ApplyWidening(TypeFlag flag) 147 { 148 if (!Source()->HasTypeFlag(flag)) { 149 return; 150 } 151 152 switch (ETSChecker::ETSChecker::ETSType(Source())) { 153 case TypeFlag::BYTE: { 154 ApplyWidening<TargetType, ByteType>(); 155 break; 156 } 157 case TypeFlag::CHAR: { 158 ApplyWidening<TargetType, CharType>(); 159 break; 160 } 161 case TypeFlag::SHORT: { 162 ApplyWidening<TargetType, ShortType>(); 163 break; 164 } 165 case TypeFlag::INT: { 166 ApplyWidening<TargetType, IntType>(); 167 break; 168 } 169 case TypeFlag::LONG: { 170 ApplyWidening<TargetType, LongType>(); 171 break; 172 } 173 case TypeFlag::FLOAT: { 174 ApplyWidening<TargetType, FloatType>(); 175 break; 176 } 177 case TypeFlag::DOUBLE: { 178 ApplyWidening<TargetType, DoubleType>(); 179 break; 180 } 181 default: { 182 return; 183 } 184 } 185 Relation()->Result(true); 186 } 187 188 template <typename TargetType, typename SourceType> ApplyWidening()189 void ApplyWidening() 190 { 191 using SType = typename SourceType::UType; 192 using TType = typename TargetType::UType; 193 SType value = reinterpret_cast<SourceType *>(Source())->GetValue(); 194 195 if (!Relation()->OnlyCheckWidening()) { 196 ASSERT(Relation()->GetNode()); 197 Relation()->GetNode()->SetTsType(Checker()->Allocator()->New<TargetType>(static_cast<TType>(value))); 198 } 199 } 200 }; 201 } // namespace panda::es2panda::checker 202 203 #endif 204