Changeset fec8bd1 for src


Ignore:
Timestamp:
Jun 14, 2023, 9:48:14 AM (14 months ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
0b0a285
Parents:
8a930c03 (diff), 8f557161 (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:
5 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Decl.cpp

    r8a930c03 rfec8bd1  
    142142bool EnumDecl::valueOf( const Decl * enumerator, long long& value ) const {
    143143        if ( enumValues.empty() ) {
    144                 long long crntVal = 0;
     144                Evaluation crntVal = {0, true, true};  // until expression is given, we know to start counting from 0
    145145                for ( const Decl * member : members ) {
    146146                        const ObjectDecl* field = strict_dynamic_cast< const ObjectDecl* >( member );
    147147                        if ( field->init ) {
    148148                                const SingleInit * init = strict_dynamic_cast< const SingleInit* >( field->init.get() );
    149                                 auto result = eval( init->value );
    150                                 if ( ! result.second ) {
     149                                crntVal = eval( init->value );
     150                                if ( ! crntVal.isEvaluableInGCC ) {
    151151                                        SemanticError( init->location, ::toString( "Non-constexpr in initialization of "
    152152                                                "enumerator: ", field ) );
    153153                                }
    154                                 crntVal = result.first;
    155154                        }
    156155                        if ( enumValues.count( field->name ) != 0 ) {
    157156                                SemanticError( location, ::toString( "Enum ", name, " has multiple members with the "   "name ", field->name ) );
    158157                        }
    159                         enumValues[ field->name ] = crntVal;
    160                         ++crntVal;
     158                        if (crntVal.hasKnownValue) {
     159                                enumValues[ field->name ] = crntVal.knownValue;
     160                        }
     161                        ++crntVal.knownValue;
    161162                }
    162163        }
  • src/Common/Eval.cc

    r8a930c03 rfec8bd1  
    9696// New AST
    9797struct EvalNew : public ast::WithShortCircuiting {
    98         long long int value = 0;                                                        // compose the result of the constant expression
    99         bool valid = true;                                                                      // true => constant expression and value is the result
    100                                                                                                                 // false => not constant expression, e.g., ++i
    101         bool cfavalid = true;                                                           // true => constant expression and value computable
    102                                                                                                                 // false => constant expression but value not computable, e.g., sizeof(int)
     98        Evaluation result = { 0, true, true };
    10399
    104100        void previsit( const ast::Node * ) { visit_children = false; }
    105         void postvisit( const ast::Node * ) { cfavalid = valid = false; }
     101        void postvisit( const ast::Node * ) { result.isEvaluableInGCC = result.hasKnownValue = false; }
    106102
    107103        void postvisit( const ast::UntypedExpr * ) {
     
    110106
    111107        void postvisit( const ast::ConstantExpr * expr ) {      // only handle int constants
    112                 value = expr->intValue();
     108                result.knownValue = expr->intValue();
     109                result.hasKnownValue = true;
     110                result.isEvaluableInGCC = true;
    113111        }
    114112
    115113        void postvisit( const ast::SizeofExpr * ) {
    116                 // do not change valid or value => let C figure it out
    117                 cfavalid = false;
     114                result.hasKnownValue = false;
     115                result.isEvaluableInGCC = true;
    118116        }
    119117
    120118        void postvisit( const ast::AlignofExpr * ) {
    121                 // do not change valid or value => let C figure it out
    122                 cfavalid = false;
     119                result.hasKnownValue = false;
     120                result.isEvaluableInGCC = true;
    123121        }
    124122
    125123        void postvisit( const ast::OffsetofExpr * ) {
    126                 // do not change valid or value => let C figure it out
    127                 cfavalid = false;
     124                result.hasKnownValue = false;
     125                result.isEvaluableInGCC = true;
    128126        }
    129127
    130128        void postvisit( const ast::LogicalExpr * expr ) {
    131                 std::pair<long long int, bool> arg1, arg2;
     129                Evaluation arg1, arg2;
    132130                arg1 = eval( expr->arg1 );
    133                 valid &= arg1.second;
    134                 if ( ! valid ) return;
     131                result.isEvaluableInGCC &= arg1.isEvaluableInGCC;
     132                if ( ! result.isEvaluableInGCC ) return;
    135133                arg2 = eval( expr->arg2 );
    136                 valid &= arg2.second;
    137                 if ( ! valid ) return;
     134                result.isEvaluableInGCC &= arg2.isEvaluableInGCC;
     135                if ( ! result.isEvaluableInGCC ) return;
     136
     137                result.hasKnownValue &= arg1.hasKnownValue;
     138                result.hasKnownValue &= arg2.hasKnownValue;
     139                if ( ! result.hasKnownValue ) return;
    138140
    139141                if ( expr->isAnd ) {
    140                         value = arg1.first && arg2.first;
     142                        result.knownValue = arg1.knownValue && arg2.knownValue;
    141143                } else {
    142                         value = arg1.first || arg2.first;
     144                        result.knownValue = arg1.knownValue || arg2.knownValue;
    143145                } // if
    144146        }
    145147
    146148        void postvisit( const ast::ConditionalExpr * expr ) {
    147                 std::pair<long long int, bool> arg1, arg2, arg3;
     149                Evaluation arg1, arg2, arg3;
    148150                arg1 = eval( expr->arg1 );
    149                 valid &= arg1.second;
    150                 if ( ! valid ) return;
     151                result.isEvaluableInGCC &= arg1.isEvaluableInGCC;
     152                if ( ! result.isEvaluableInGCC ) return;
    151153                arg2 = eval( expr->arg2 );
    152                 valid &= arg2.second;
    153                 if ( ! valid ) return;
     154                result.isEvaluableInGCC &= arg2.isEvaluableInGCC;
     155                if ( ! result.isEvaluableInGCC ) return;
    154156                arg3 = eval( expr->arg3 );
    155                 valid &= arg3.second;
    156                 if ( ! valid ) return;
    157 
    158                 value = arg1.first ? arg2.first : arg3.first;
     157                result.isEvaluableInGCC &= arg3.isEvaluableInGCC;
     158                if ( ! result.isEvaluableInGCC ) return;
     159
     160                result.hasKnownValue &= arg1.hasKnownValue;
     161                result.hasKnownValue &= arg2.hasKnownValue;
     162                result.hasKnownValue &= arg3.hasKnownValue;
     163                if ( ! result.hasKnownValue ) return;
     164
     165                result.knownValue = arg1.knownValue ? arg2.knownValue : arg3.knownValue;
    159166        }
    160167
    161168        void postvisit( const ast::CastExpr * expr ) {         
    162                 // cfa-cc generates a cast before every constant and many other places, e.g., (int)3, so the cast argument must
    163                 // be evaluated to get the constant value.
    164                 auto arg = eval(expr->arg);
    165                 valid = arg.second;
    166                 value = arg.first;
    167                 cfavalid = false;
     169                // cfa-cc generates a cast before every constant and many other places, e.g., (int)3,
     170                // so we must use the value from the cast argument, even though we lack any basis for evaluating wraparound effects, etc
     171                result = eval(expr->arg);
    168172        }
    169173
    170174        void postvisit( const ast::VariableExpr * expr ) {
     175                result.hasKnownValue = false;
     176                result.isEvaluableInGCC = false;
    171177                if ( const ast::EnumInstType * inst = dynamic_cast<const ast::EnumInstType *>(expr->result.get()) ) {
    172178                        if ( const ast::EnumDecl * decl = inst->base ) {
    173                                 if ( decl->valueOf( expr->var, value ) ) { // value filled by valueOf
    174                                         return;
    175                                 }
     179                                result.isEvaluableInGCC = true;
     180                                result.hasKnownValue = decl->valueOf( expr->var, result.knownValue ); // result.knownValue filled by valueOf
    176181                        }
    177182                }
    178                 valid = false;
    179183        }
    180184
    181185        void postvisit( const ast::ApplicationExpr * expr ) {
    182186                const ast::DeclWithType * function = ast::getFunction(expr);
    183                 if ( ! function || function->linkage != ast::Linkage::Intrinsic ) { valid = false; return; }
     187                if ( ! function || function->linkage != ast::Linkage::Intrinsic ) {
     188                        result.isEvaluableInGCC = false;
     189                        result.hasKnownValue = false;
     190                        return;
     191                }
    184192                const std::string & fname = function->name;
    185193                assertf( expr->args.size() == 1 || expr->args.size() == 2, "Intrinsic function with %zd arguments: %s", expr->args.size(), fname.c_str() );
     
    187195                if ( expr->args.size() == 1 ) {
    188196                        // pre/postfix operators ++ and -- => assignment, which is not constant
    189                         std::pair<long long int, bool> arg1;
     197                        Evaluation arg1;
    190198                        arg1 = eval(expr->args.front());
    191                         valid &= arg1.second;
    192                         if ( ! valid ) return;
     199                        result.isEvaluableInGCC &= arg1.isEvaluableInGCC;
     200                        if ( ! result.isEvaluableInGCC ) return;
     201
     202                        result.hasKnownValue &= arg1.hasKnownValue;
     203                        if ( ! result.hasKnownValue ) return;
    193204
    194205                        if (fname == "+?") {
    195                                 value = arg1.first;
     206                                result.knownValue = arg1.knownValue;
    196207                        } else if (fname == "-?") {
    197                                 value = -arg1.first;
     208                                result.knownValue = -arg1.knownValue;
    198209                        } else if (fname == "~?") {
    199                                 value = ~arg1.first;
     210                                result.knownValue = ~arg1.knownValue;
    200211                        } else if (fname == "!?") {
    201                                 value = ! arg1.first;
     212                                result.knownValue = ! arg1.knownValue;
    202213                        } else {
    203                                 valid = false;
     214                                result.isEvaluableInGCC = false;
     215                                result.hasKnownValue = false;
    204216                        } // if
    205217                } else { // => expr->args.size() == 2
    206218                        // infix assignment operators => assignment, which is not constant
    207                         std::pair<long long int, bool> arg1, arg2;
     219                        Evaluation arg1, arg2;
    208220                        arg1 = eval(expr->args.front());
    209                         valid &= arg1.second;
    210                         if ( ! valid ) return;
     221                        result.isEvaluableInGCC &= arg1.isEvaluableInGCC;
     222                        if ( ! result.isEvaluableInGCC ) return;
    211223                        arg2 = eval(expr->args.back());
    212                         valid &= arg2.second;
    213                         if ( ! valid ) return;
     224                        result.isEvaluableInGCC &= arg2.isEvaluableInGCC;
     225                        if ( ! result.isEvaluableInGCC ) return;
     226
     227                        result.hasKnownValue &= arg1.hasKnownValue;
     228                        result.hasKnownValue &= arg2.hasKnownValue;
     229                        if ( ! result.hasKnownValue ) return;
    214230
    215231                        if (fname == "?+?") {
    216                                 value = arg1.first + arg2.first;
     232                                result.knownValue = arg1.knownValue + arg2.knownValue;
    217233                        } else if (fname == "?-?") {
    218                                 value = arg1.first - arg2.first;
     234                                result.knownValue = arg1.knownValue - arg2.knownValue;
    219235                        } else if (fname == "?*?") {
    220                                 value = arg1.first * arg2.first;
     236                                result.knownValue = arg1.knownValue * arg2.knownValue;
    221237                        } else if (fname == "?/?") {
    222                                 if ( arg2.first ) value = arg1.first / arg2.first;
     238                                if ( arg2.knownValue ) result.knownValue = arg1.knownValue / arg2.knownValue;
    223239                        } else if (fname == "?%?") {
    224                                 if ( arg2.first ) value = arg1.first % arg2.first;
     240                                if ( arg2.knownValue ) result.knownValue = arg1.knownValue % arg2.knownValue;
    225241                        } else if (fname == "?<<?") {
    226                                 value = arg1.first << arg2.first;
     242                                result.knownValue = arg1.knownValue << arg2.knownValue;
    227243                        } else if (fname == "?>>?") {
    228                                 value = arg1.first >> arg2.first;
     244                                result.knownValue = arg1.knownValue >> arg2.knownValue;
    229245                        } else if (fname == "?<?") {
    230                                 value = arg1.first < arg2.first;
     246                                result.knownValue = arg1.knownValue < arg2.knownValue;
    231247                        } else if (fname == "?>?") {
    232                                 value = arg1.first > arg2.first;
     248                                result.knownValue = arg1.knownValue > arg2.knownValue;
    233249                        } else if (fname == "?<=?") {
    234                                 value = arg1.first <= arg2.first;
     250                                result.knownValue = arg1.knownValue <= arg2.knownValue;
    235251                        } else if (fname == "?>=?") {
    236                                 value = arg1.first >= arg2.first;
     252                                result.knownValue = arg1.knownValue >= arg2.knownValue;
    237253                        } else if (fname == "?==?") {
    238                                 value = arg1.first == arg2.first;
     254                                result.knownValue = arg1.knownValue == arg2.knownValue;
    239255                        } else if (fname == "?!=?") {
    240                                 value = arg1.first != arg2.first;
     256                                result.knownValue = arg1.knownValue != arg2.knownValue;
    241257                        } else if (fname == "?&?") {
    242                                 value = arg1.first & arg2.first;
     258                                result.knownValue = arg1.knownValue & arg2.knownValue;
    243259                        } else if (fname == "?^?") {
    244                                 value = arg1.first ^ arg2.first;
     260                                result.knownValue = arg1.knownValue ^ arg2.knownValue;
    245261                        } else if (fname == "?|?") {
    246                                 value = arg1.first | arg2.first;
     262                                result.knownValue = arg1.knownValue | arg2.knownValue;
    247263                        } else {
    248                                 valid = false;
     264                                result.isEvaluableInGCC = false;
     265                                result.hasKnownValue = false;
    249266                        }
    250267                } // if
     
    263280}
    264281
    265 std::pair<long long int, bool> eval( const ast::Expr * expr ) {
    266         ast::Pass<EvalNew> ev;
     282Evaluation eval( const ast::Expr * expr ) {
    267283        if ( expr ) {
    268                 expr->accept( ev );
    269                 return std::make_pair( ev.core.value, ev.core.valid );
     284
     285                return ast::Pass<EvalNew>::read(expr);
     286                // Evaluation ret = ast::Pass<EvalNew>::read(expr);
     287                // ret.knownValue = 777;
     288                // return ret;
     289
    270290        } else {
    271                 return std::make_pair( 0, false );
     291                return { 0, false, false };
    272292        }
    273293}
  • src/Common/Eval.h

    r8a930c03 rfec8bd1  
    2323}
    2424
     25struct Evaluation {
     26        long long int knownValue;
     27        bool hasKnownValue;
     28        bool isEvaluableInGCC;
     29};
     30
    2531/// Evaluates expr as a long long int.
    2632/// If second is false, expr could not be evaluated.
    2733std::pair<long long int, bool> eval(const Expression * expr);
    28 std::pair<long long int, bool> eval(const ast::Expr * expr);
     34Evaluation eval(const ast::Expr * expr);
    2935
    3036// Local Variables: //
  • src/ResolvExpr/CurrentObject.cc

    r8a930c03 rfec8bd1  
    689689
    690690                        auto arg = eval( expr );
    691                         index = arg.first;
     691                        assertf( arg.hasKnownValue, "Non-evaluable expression made it to IndexIterator" );
     692                        index = arg.knownValue;
    692693
    693694                        // if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) {
     
    728729                size_t getSize( const Expr * expr ) {
    729730                        auto res = eval( expr );
    730                         if ( !res.second ) {
     731                        if ( !res.hasKnownValue ) {
    731732                                SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) );
    732733                        }
    733                         return res.first;
     734                        return res.knownValue;
    734735                }
    735736
  • src/ResolvExpr/Resolver.cc

    r8a930c03 rfec8bd1  
    13411341                                        auto mutAttr = mutate(attr);
    13421342                                        mutAttr->params.front() = resolved;
    1343                                         if (! result.second) {
     1343                                        if (! result.hasKnownValue) {
    13441344                                                SemanticWarning(loc, Warning::GccAttributes,
    13451345                                                        toCString( name, " priorities must be integers from 0 to 65535 inclusive: ", arg ) );
    13461346                                        }
    13471347                                        else {
    1348                                                 auto priority = result.first;
     1348                                                auto priority = result.knownValue;
    13491349                                                if (priority < 101) {
    13501350                                                        SemanticWarning(loc, Warning::GccAttributes,
Note: See TracChangeset for help on using the changeset viewer.