Changeset 120867e for src/Common
- Timestamp:
- Jul 1, 2022, 5:31:57 PM (2 years ago)
- Branches:
- ADT, ast-experimental, master, pthread-emulation, qualifiedEnum
- Children:
- 7991c7d
- Parents:
- 1ed3fe7c
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Common/Eval.cc
r1ed3fe7c r120867e 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jul 24 15:09:06 201913 // Update Count : 6412 // Last Modified On : Fri Jul 1 08:41:03 2022 13 // Update Count : 117 14 14 // 15 15 … … 17 17 18 18 #include "Common/PassVisitor.h" 19 #include "CodeGen/OperatorTable.h" // access: OperatorInfo 19 20 #include "AST/Pass.hpp" 20 21 #include "InitTweak/InitTweak.h" … … 24 25 // Old AST 25 26 struct EvalOld : public WithShortCircuiting { 26 long long int value = 0; 27 bool valid = true; 27 long long int value = 0; // compose the result of the constant expression 28 bool valid = true; // true => constant expression and value is the result 29 // false => not constant expression, e.g., ++i 30 bool cfavalid = true; // true => constant expression and value computable 31 // false => constant expression but value not computable, e.g., sizeof(int) 28 32 29 33 void previsit( const BaseSyntaxNode * ) { visit_children = false; } … … 89 93 // New AST 90 94 struct EvalNew : public ast::WithShortCircuiting { 91 long long int value = 0; 92 bool valid = true; 95 long long int value = 0; // compose the result of the constant expression 96 bool valid = true; // true => constant expression and value is the result 97 // false => not constant expression, e.g., ++i 98 bool cfavalid = true; // true => constant expression and value computable 99 // false => constant expression but value not computable, e.g., sizeof(int) 93 100 94 101 void previsit( const ast::Node * ) { visit_children = false; } 95 void postvisit( const ast::Node * ) { valid = false; } 96 97 void postvisit( const ast::ConstantExpr * expr ) { 102 void postvisit( const ast::Node * ) { cfavalid = valid = false; } 103 104 void postvisit( const ast::UntypedExpr * ) { 105 assertf( false, "UntypedExpr in constant expression evaluation" ); // FIX ME, resolve variable 106 } 107 108 void postvisit( const ast::ConstantExpr * expr ) { // only handle int constants 98 109 value = expr->intValue(); 99 110 } 100 111 101 void postvisit( const ast::SizeofExpr * expr ) { 102 if ( expr->expr ) value = eval(expr->expr).first; 103 else if ( expr->type ) value = eval(expr->expr).first; 104 else SemanticError( expr->location, ::toString( "Internal error: SizeofExpr has no expression or type value" ) ); 105 } 106 107 void postvisit( const ast::CastExpr * expr ) { 112 void postvisit( const ast::SizeofExpr * ) { 113 // do not change valid or value => let C figure it out 114 cfavalid = false; 115 } 116 117 void postvisit( const ast::AlignofExpr * ) { 118 // do not change valid or value => let C figure it out 119 cfavalid = false; 120 } 121 122 void postvisit( const ast::OffsetofExpr * ) { 123 // do not change valid or value => let C figure it out 124 cfavalid = false; 125 } 126 127 void postvisit( const ast::LogicalExpr * expr ) { 128 std::pair<long long int, bool> arg1, arg2; 129 arg1 = eval( expr->arg1 ); 130 valid &= arg1.second; 131 if ( ! valid ) return; 132 arg2 = eval( expr->arg2 ); 133 valid &= arg2.second; 134 if ( ! valid ) return; 135 136 if ( expr->isAnd ) { 137 value = arg1.first && arg2.first; 138 } else { 139 value = arg1.first || arg2.first; 140 } // if 141 } 142 143 void postvisit( const ast::ConditionalExpr * expr ) { 144 std::pair<long long int, bool> arg1, arg2, arg3; 145 arg1 = eval( expr->arg1 ); 146 valid &= arg1.second; 147 if ( ! valid ) return; 148 arg2 = eval( expr->arg2 ); 149 valid &= arg2.second; 150 if ( ! valid ) return; 151 arg3 = eval( expr->arg3 ); 152 valid &= arg3.second; 153 if ( ! valid ) return; 154 155 value = arg1.first ? arg2.first : arg3.first; 156 } 157 158 void postvisit( const ast::CastExpr * expr ) { 159 // cfa-cc generates a cast before every constant and many other places, e.g., (int)3, so the cast argument must 160 // be evaluated to get the constant value. 108 161 auto arg = eval(expr->arg); 109 162 valid = arg.second; 110 163 value = arg.first; 111 // TODO: perform type conversion on value if valid112 } 113 114 void postvisit( const ast::VariableExpr * expr ) { // No hit164 cfavalid = false; 165 } 166 167 void postvisit( const ast::VariableExpr * expr ) { 115 168 if ( const ast::EnumInstType * inst = dynamic_cast<const ast::EnumInstType *>(expr->result.get()) ) { 116 169 if ( const ast::EnumDecl * decl = inst->base ) { … … 128 181 const std::string & fname = function->name; 129 182 assertf( expr->args.size() == 1 || expr->args.size() == 2, "Intrinsic function with %zd arguments: %s", expr->args.size(), fname.c_str() ); 130 std::pair<long long int, bool> arg1, arg2; 131 arg1 = eval(expr->args.front()); 132 valid = valid && arg1.second; 133 if ( ! valid ) return; 134 if ( expr->args.size() == 2 ) { 183 184 if ( expr->args.size() == 1 ) { 185 // pre/postfix operators ++ and -- => assignment, which is not constant 186 std::pair<long long int, bool> arg1; 187 arg1 = eval(expr->args.front()); 188 valid &= arg1.second; 189 if ( ! valid ) return; 190 191 if (fname == "+?") { 192 value = arg1.first; 193 } else if (fname == "-?") { 194 value = -arg1.first; 195 } else if (fname == "~?") { 196 value = ~arg1.first; 197 } else if (fname == "!?") { 198 value = ! arg1.first; 199 } else { 200 valid = false; 201 } // if 202 } else { // => expr->args.size() == 2 203 // infix assignment operators => assignment, which is not constant 204 std::pair<long long int, bool> arg1, arg2; 205 arg1 = eval(expr->args.front()); 206 valid &= arg1.second; 207 if ( ! valid ) return; 135 208 arg2 = eval(expr->args.back()); 136 valid = valid && arg2.second; 137 if ( ! valid ) return; 138 } 139 if (fname == "?+?") { 140 value = arg1.first + arg2.first; 141 } else if (fname == "?-?") { 142 value = arg1.first - arg2.first; 143 } else if (fname == "?*?") { 144 value = arg1.first * arg2.first; 145 } else if (fname == "?/?") { 146 value = arg1.first / arg2.first; 147 } else if (fname == "?%?") { 148 value = arg1.first % arg2.first; 149 } else { 150 valid = false; 151 } 209 valid &= arg2.second; 210 if ( ! valid ) return; 211 212 if (fname == "?+?") { 213 value = arg1.first + arg2.first; 214 } else if (fname == "?-?") { 215 value = arg1.first - arg2.first; 216 } else if (fname == "?*?") { 217 value = arg1.first * arg2.first; 218 } else if (fname == "?/?") { 219 value = arg1.first / arg2.first; 220 } else if (fname == "?%?") { 221 value = arg1.first % arg2.first; 222 } else if (fname == "?<<?") { 223 value = arg1.first << arg2.first; 224 } else if (fname == "?>>?") { 225 value = arg1.first >> arg2.first; 226 } else if (fname == "?<?") { 227 value = arg1.first < arg2.first; 228 } else if (fname == "?>?") { 229 value = arg1.first > arg2.first; 230 } else if (fname == "?<=?") { 231 value = arg1.first <= arg2.first; 232 } else if (fname == "?>=?") { 233 value = arg1.first >= arg2.first; 234 } else if (fname == "?==?") { 235 value = arg1.first == arg2.first; 236 } else if (fname == "?!=?") { 237 value = arg1.first != arg2.first; 238 } else if (fname == "?&?") { 239 value = arg1.first & arg2.first; 240 } else if (fname == "?^?") { 241 value = arg1.first ^ arg2.first; 242 } else if (fname == "?|?") { 243 value = arg1.first | arg2.first; 244 } else { 245 valid = false; 246 } 247 } // if 152 248 // TODO: implement other intrinsic functions 153 249 } 154 250 }; 155 251 156 std::pair<long long int, bool> eval( const Expression * expr ) {252 std::pair<long long int, bool> eval( const Expression * expr ) { 157 253 PassVisitor<EvalOld> ev; 158 if ( expr) {159 expr->accept( ev);160 return std::make_pair( ev.pass.value, ev.pass.valid);254 if ( expr ) { 255 expr->accept( ev ); 256 return std::make_pair( ev.pass.value, ev.pass.valid ); 161 257 } else { 162 return std::make_pair( 0, false);258 return std::make_pair( 0, false ); 163 259 } 164 260 } 165 261 166 std::pair<long long int, bool> eval( const ast::Expr * expr) {262 std::pair<long long int, bool> eval( const ast::Expr * expr ) { 167 263 ast::Pass<EvalNew> ev; 168 if ( expr) {169 expr->accept( ev);170 return std::make_pair( ev.core.value, ev.core.valid);264 if ( expr ) { 265 expr->accept( ev ); 266 return std::make_pair( ev.core.value, ev.core.valid ); 171 267 } else { 172 return std::make_pair( 0, false);268 return std::make_pair( 0, false ); 173 269 } 174 270 }
Note: See TracChangeset
for help on using the changeset viewer.