Changeset 25404c7 for src


Ignore:
Timestamp:
Jul 5, 2022, 9:36:59 AM (4 years ago)
Author:
Thierry Delisle <tdelisle@…>
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.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/Common/Eval.cc

    r06bdba4 r25404c7  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 24 15:09:06 2019
    13 // Update Count     : 64
     12// Last Modified On : Fri Jul  1 08:41:03 2022
     13// Update Count     : 117
    1414//
    1515
     
    1717
    1818#include "Common/PassVisitor.h"
     19#include "CodeGen/OperatorTable.h"                                              // access: OperatorInfo
    1920#include "AST/Pass.hpp"
    2021#include "InitTweak/InitTweak.h"
     
    2425// Old AST
    2526struct 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)
    2832
    2933        void previsit( const BaseSyntaxNode * ) { visit_children = false; }
     
    8993// New AST
    9094struct 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)
    93100
    94101        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
    98109                value = expr->intValue();
    99110        }
    100111
    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.
    108161                auto arg = eval(expr->arg);
    109162                valid = arg.second;
    110163                value = arg.first;
    111                 // TODO: perform type conversion on value if valid
    112         }
    113 
    114         void postvisit( const ast::VariableExpr * expr ) { // No hit
     164                cfavalid = false;
     165        }
     166
     167        void postvisit( const ast::VariableExpr * expr ) {
    115168                if ( const ast::EnumInstType * inst = dynamic_cast<const ast::EnumInstType *>(expr->result.get()) ) {
    116169                        if ( const ast::EnumDecl * decl = inst->base ) {
     
    128181                const std::string & fname = function->name;
    129182                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;
    135208                        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
    152248                // TODO: implement other intrinsic functions
    153249        }
    154250};
    155251
    156 std::pair<long long int, bool> eval( const Expression * expr) {
     252std::pair<long long int, bool> eval( const Expression * expr ) {
    157253        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 );
    161257        } else {
    162                 return std::make_pair(0, false);
     258                return std::make_pair( 0, false );
    163259        }
    164260}
    165261
    166 std::pair<long long int, bool> eval(const ast::Expr * expr) {
     262std::pair<long long int, bool> eval( const ast::Expr * expr ) {
    167263        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 );
    171267        } else {
    172                 return std::make_pair(0, false);
     268                return std::make_pair( 0, false );
    173269        }
    174270}
  • src/Parser/parser.yy

    r06bdba4 r25404c7  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat May 14 09:16:22 2022
    13 // Update Count     : 5401
     12// Last Modified On : Fri Jul  1 15:35:08 2022
     13// Update Count     : 5405
    1414//
    1515
     
    24412441        // empty
    24422442                { $$ = nullptr; }
    2443         // | '=' constant_expression
    2444         //      { $$ = $2; }
    2445         | simple_assignment_operator initializer
    2446                 { $$ = $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 ); }
    24472447        ;
    24482448
  • src/ResolvExpr/CurrentObject.cc

    r06bdba4 r25404c7  
    99// Author           : Rob Schluntz
    1010// Created On       : Tue Jun 13 15:28:32 2017
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Tue Jun 13 15:28:44 2017
    13 // Update Count     : 2
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Jul  1 09:16:01 2022
     13// Update Count     : 15
    1414//
    1515
     
    158158
    159159        private:
    160                 void setSize( Expression * expr ) { // replace this logic with an eval call
    161                         auto res = eval(expr);
     160                void setSize( Expression * expr ) {
     161                        auto res = eval( expr );
    162162                        if (res.second) {
    163163                                size = res.first;
     
    170170                void setPosition( Expression * expr ) {
    171171                        // 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                        // }
    192196                }
    193197
     
    329333                                        assertf( false, "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
    330334                                } 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() );
    332336                                } // if
    333337                        } // if
     
    637641
    638642                void setSize( const Expr * expr ) {
    639                         auto res = eval(expr);
     643                        auto res = eval( expr );
    640644                        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 ) );
    643646                        }
    644647                        size = res.first;
     
    646649
    647650        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 ) {
    650652                        PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
    651653                        memberIter.reset( createMemberIterator( loc, base ) );
     
    660662                        // enumeration constants, character constants, sizeof expressions, alignof expressions,
    661663                        // 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                        // }
    680682                }
    681683
     
    723725                                std::deque< InitAlternative > ret = memberIter->first();
    724726                                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 ) );
    727728                                }
    728729                                return ret;
     
    788789                                        return;
    789790                                }
    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() );
    792792                        } 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() );
    795794                        }
    796795                }
  • src/SynTree/AggregateDecl.cc

    r06bdba4 r25404c7  
    1010// Created On       : Sun May 17 23:56:39 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Dec 16 15:07:20 2019
    13 // Update Count     : 31
     12// Last Modified On : Fri Jul  1 09:12:33 2022
     13// Update Count     : 32
    1414//
    1515
     
    125125                                SingleInit * init = strict_dynamic_cast< SingleInit * >( field->init );
    126126                                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" ) );
    128128                                currentValue = result.first;
    129129                        }
Note: See TracChangeset for help on using the changeset viewer.