Changes in src/Common/Eval.cc [120867e:f135b50]
- File:
-
- 1 edited
-
src/Common/Eval.cc (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Common/Eval.cc
r120867e rf135b50 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jul 1 08:41:03 202213 // Update Count : 11712 // Last Modified On : Wed Jul 24 15:09:06 2019 13 // Update Count : 64 14 14 // 15 15 … … 17 17 18 18 #include "Common/PassVisitor.h" 19 #include "CodeGen/OperatorTable.h" // access: OperatorInfo20 19 #include "AST/Pass.hpp" 21 20 #include "InitTweak/InitTweak.h" … … 25 24 // Old AST 26 25 struct EvalOld : public WithShortCircuiting { 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) 26 long long int value = 0; 27 bool valid = true; 32 28 33 29 void previsit( const BaseSyntaxNode * ) { visit_children = false; } … … 93 89 // New AST 94 90 struct EvalNew : public ast::WithShortCircuiting { 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) 91 long long int value = 0; 92 bool valid = true; 100 93 101 94 void previsit( const ast::Node * ) { visit_children = false; } 102 void postvisit( const ast::Node * ) { cfavalid =valid = false; }95 void postvisit( const ast::Node * ) { valid = false; } 103 96 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 97 void postvisit( const ast::ConstantExpr * expr ) { 109 98 value = expr->intValue(); 110 99 } 111 100 112 void postvisit( const ast::SizeofExpr * ) { 113 // do not change valid or value => let C figure it out 114 cfavalid = false; 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" ) ); 115 105 } 116 106 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. 107 void postvisit( const ast::CastExpr * expr ) { 161 108 auto arg = eval(expr->arg); 162 109 valid = arg.second; 163 110 value = arg.first; 164 cfavalid = false;111 // TODO: perform type conversion on value if valid 165 112 } 166 113 167 void postvisit( const ast::VariableExpr * expr ) { 114 void postvisit( const ast::VariableExpr * expr ) { // No hit 168 115 if ( const ast::EnumInstType * inst = dynamic_cast<const ast::EnumInstType *>(expr->result.get()) ) { 169 116 if ( const ast::EnumDecl * decl = inst->base ) { … … 181 128 const std::string & fname = function->name; 182 129 assertf( expr->args.size() == 1 || expr->args.size() == 2, "Intrinsic function with %zd arguments: %s", expr->args.size(), fname.c_str() ); 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; 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 ) { 135 arg2 = eval(expr->args.back()); 136 valid = valid && arg2.second; 189 137 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; 208 arg2 = eval(expr->args.back()); 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 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 } 248 152 // TODO: implement other intrinsic functions 249 153 } 250 154 }; 251 155 252 std::pair<long long int, bool> eval( const Expression * expr ) {156 std::pair<long long int, bool> eval( const Expression * expr) { 253 157 PassVisitor<EvalOld> ev; 254 if ( expr) {255 expr->accept( ev);256 return std::make_pair( ev.pass.value, ev.pass.valid);158 if (expr) { 159 expr->accept(ev); 160 return std::make_pair(ev.pass.value, ev.pass.valid); 257 161 } else { 258 return std::make_pair( 0, false);162 return std::make_pair(0, false); 259 163 } 260 164 } 261 165 262 std::pair<long long int, bool> eval( const ast::Expr * expr) {166 std::pair<long long int, bool> eval(const ast::Expr * expr) { 263 167 ast::Pass<EvalNew> ev; 264 if ( expr) {265 expr->accept( ev);266 return std::make_pair( ev.core.value, ev.core.valid);168 if (expr) { 169 expr->accept(ev); 170 return std::make_pair(ev.core.value, ev.core.valid); 267 171 } else { 268 return std::make_pair( 0, false);172 return std::make_pair(0, false); 269 173 } 270 174 }
Note:
See TracChangeset
for help on using the changeset viewer.