Changeset 5668740 for src/Common


Ignore:
Timestamp:
Jun 14, 2023, 11:35:49 AM (21 months ago)
Author:
caparsons <caparson@…>
Branches:
master
Children:
7e4bd9b6
Parents:
32a4f3e (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/Common
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified src/Common/Eval.cc

    r32a4f3e r5668740  
    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}
  • TabularUnified src/Common/Eval.h

    r32a4f3e r5668740  
    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: //
Note: See TracChangeset for help on using the changeset viewer.