- Timestamp:
- Jul 5, 2022, 9:36:59 AM (4 years ago)
- Branches:
- ADT, ast-experimental, master, pthread-emulation, qualifiedEnum, stuck-waitfor-destruct
- Children:
- d4b37ab
- Parents:
- 06bdba4 (diff), 9c6443e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- src
- Files:
-
- 4 edited
-
Common/Eval.cc (modified) (5 diffs)
-
Parser/parser.yy (modified) (2 diffs)
-
ResolvExpr/CurrentObject.cc (modified) (9 diffs)
-
SynTree/AggregateDecl.cc (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Common/Eval.cc
r06bdba4 r25404c7 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 } -
src/Parser/parser.yy
r06bdba4 r25404c7 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat May 14 09:16:22202213 // Update Count : 540 112 // Last Modified On : Fri Jul 1 15:35:08 2022 13 // Update Count : 5405 14 14 // 15 15 … … 2441 2441 // empty 2442 2442 { $$ = nullptr; } 2443 // | '=' constant_expression2444 // { $$ = $2; }2445 | simple_assignment_operator initializer2446 { $$ = $1 == OperKinds::Assign ? $2 : $2->set_maybeConstructed( false ); }2443 | '=' constant_expression { $$ = new InitializerNode( $2 ); } 2444 | '=' '{' initializer_list_opt comma_opt '}' { $$ = new InitializerNode( $3, true ); } 2445 // | simple_assignment_operator initializer 2446 // { $$ = $1 == OperKinds::Assign ? $2 : $2->set_maybeConstructed( false ); } 2447 2447 ; 2448 2448 -
src/ResolvExpr/CurrentObject.cc
r06bdba4 r25404c7 9 9 // Author : Rob Schluntz 10 10 // Created On : Tue Jun 13 15:28:32 2017 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Tue Jun 13 15:28:44 201713 // Update Count : 211 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jul 1 09:16:01 2022 13 // Update Count : 15 14 14 // 15 15 … … 158 158 159 159 private: 160 void setSize( Expression * expr ) { // replace this logic with an eval call161 auto res = eval( expr);160 void setSize( Expression * expr ) { 161 auto res = eval( expr ); 162 162 if (res.second) { 163 163 size = res.first; … … 170 170 void setPosition( Expression * expr ) { 171 171 // need to permit integer-constant-expressions, including: integer constants, enumeration constants, character constants, sizeof expressions, _Alignof expressions, cast expressions 172 if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) { 173 try { 174 index = constExpr->intValue(); 175 } catch( SemanticErrorException & ) { 176 SemanticError( expr, "Constant expression of non-integral type in array designator: " ); 177 } 178 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 179 setPosition( castExpr->get_arg() ); 180 } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) { 181 EnumInstType * inst = dynamic_cast<EnumInstType *>( varExpr->get_result() ); 182 assertf( inst, "ArrayIterator given variable that isn't an enum constant : %s", toString( expr ).c_str() ); 183 long long int value; 184 if ( inst->baseEnum->valueOf( varExpr->var, value ) ) { 185 index = value; 186 } 187 } else if ( dynamic_cast< SizeofExpr * >( expr ) || dynamic_cast< AlignofExpr * >( expr ) ) { 188 index = 0; // xxx - get actual sizeof/alignof value? 189 } else { 190 assertf( false, "bad designator given to ArrayIterator: %s", toString( expr ).c_str() ); 191 } 172 auto arg = eval( expr ); 173 index = arg.first; 174 return; 175 176 // if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) { 177 // try { 178 // index = constExpr->intValue(); 179 // } catch( SemanticErrorException & ) { 180 // SemanticError( expr, "Constant expression of non-integral type in array designator: " ); 181 // } 182 // } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 183 // setPosition( castExpr->get_arg() ); 184 // } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) { 185 // EnumInstType * inst = dynamic_cast<EnumInstType *>( varExpr->get_result() ); 186 // assertf( inst, "ArrayIterator given variable that isn't an enum constant : %s", toString( expr ).c_str() ); 187 // long long int value; 188 // if ( inst->baseEnum->valueOf( varExpr->var, value ) ) { 189 // index = value; 190 // } 191 // } else if ( dynamic_cast< SizeofExpr * >( expr ) || dynamic_cast< AlignofExpr * >( expr ) ) { 192 // index = 0; // xxx - get actual sizeof/alignof value? 193 // } else { 194 // assertf( false, "4 bad designator given to ArrayIterator: %s", toString( expr ).c_str() ); 195 // } 192 196 } 193 197 … … 329 333 assertf( false, "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() ); 330 334 } else { 331 assertf( false, " bad designator given to %s: %s", kind.c_str(), toString( designators.front() ).c_str() );335 assertf( false, "3 bad designator given to %s: %s", kind.c_str(), toString( designators.front() ).c_str() ); 332 336 } // if 333 337 } // if … … 637 641 638 642 void setSize( const Expr * expr ) { 639 auto res = eval( expr);643 auto res = eval( expr ); 640 644 if ( ! res.second ) { 641 SemanticError( location, 642 toString("Array designator must be a constant expression: ", expr ) ); 645 SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) ); 643 646 } 644 647 size = res.first; … … 646 649 647 650 public: 648 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) 649 : location( loc ), array( at ), base( at->base ) { 651 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) : location( loc ), array( at ), base( at->base ) { 650 652 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; ) 651 653 memberIter.reset( createMemberIterator( loc, base ) ); … … 660 662 // enumeration constants, character constants, sizeof expressions, alignof expressions, 661 663 // cast expressions 662 if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) { 663 try {664 index = constExpr->intValue();665 } catch ( SemanticErrorException & ) {666 SemanticError( expr, 667 "Constant expression of non-integral type in array designator: " );668 }669 } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) {670 setPosition( castExpr->arg );671 } else if (672 dynamic_cast< const SizeofExpr * >( expr )673 || dynamic_cast< const AlignofExpr * >( expr )674 ) {675 index = 0;676 } else {677 assertf( false,678 "bad designator given to ArrayIterator: %s", toString( expr ).c_str() );679 }664 665 auto arg = eval( expr ); 666 index = arg.first; 667 return; 668 669 // if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) { 670 // try { 671 // index = constExpr->intValue(); 672 // } catch ( SemanticErrorException & ) { 673 // SemanticError( expr, "Constant expression of non-integral type in array designator: " ); 674 // } 675 // } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) { 676 // setPosition( castExpr->arg ); 677 // } else if ( dynamic_cast< const SizeofExpr * >( expr ) || dynamic_cast< const AlignofExpr * >( expr ) ) { 678 // index = 0; 679 // } else { 680 // assertf( false, "2 bad designator given to ArrayIterator: %s", toString( expr ).c_str() ); 681 // } 680 682 } 681 683 … … 723 725 std::deque< InitAlternative > ret = memberIter->first(); 724 726 for ( InitAlternative & alt : ret ) { 725 alt.designation.get_and_mutate()->designators.emplace_front( 726 ConstantExpr::from_ulong( location, index ) ); 727 alt.designation.get_and_mutate()->designators.emplace_front( ConstantExpr::from_ulong( location, index ) ); 727 728 } 728 729 return ret; … … 788 789 return; 789 790 } 790 assertf( false, 791 "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() ); 791 assertf( false, "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() ); 792 792 } else { 793 assertf( false, 794 "bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() ); 793 assertf( false, "1 bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() ); 795 794 } 796 795 } -
src/SynTree/AggregateDecl.cc
r06bdba4 r25404c7 10 10 // Created On : Sun May 17 23:56:39 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Dec 16 15:07:20 201913 // Update Count : 3 112 // Last Modified On : Fri Jul 1 09:12:33 2022 13 // Update Count : 32 14 14 // 15 15 … … 125 125 SingleInit * init = strict_dynamic_cast< SingleInit * >( field->init ); 126 126 auto result = eval( init->value ); 127 if ( ! result.second ) SemanticError( init->location, toString( " Non-constexpr in initialization of enumerator: ", field) );127 if ( ! result.second ) SemanticError( init->location, toString( "Enumerator value for '", field, "' is not an integer constant" ) ); 128 128 currentValue = result.first; 129 129 }
Note:
See TracChangeset
for help on using the changeset viewer.