Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Common/Eval.cc

    r120867e rf135b50  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul  1 08:41:03 2022
    13 // Update Count     : 117
     12// Last Modified On : Wed Jul 24 15:09:06 2019
     13// Update Count     : 64
    1414//
    1515
     
    1717
    1818#include "Common/PassVisitor.h"
    19 #include "CodeGen/OperatorTable.h"                                              // access: OperatorInfo
    2019#include "AST/Pass.hpp"
    2120#include "InitTweak/InitTweak.h"
     
    2524// Old AST
    2625struct 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;
    3228
    3329        void previsit( const BaseSyntaxNode * ) { visit_children = false; }
     
    9389// New AST
    9490struct 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;
    10093
    10194        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; }
    10396
    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 ) {
    10998                value = expr->intValue();
    11099        }
    111100
    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" ) );
    115105        }
    116106
    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 ) {
    161108                auto arg = eval(expr->arg);
    162109                valid = arg.second;
    163110                value = arg.first;
    164                 cfavalid = false;
     111                // TODO: perform type conversion on value if valid
    165112        }
    166113
    167         void postvisit( const ast::VariableExpr * expr ) {
     114        void postvisit( const ast::VariableExpr * expr ) { // No hit
    168115                if ( const ast::EnumInstType * inst = dynamic_cast<const ast::EnumInstType *>(expr->result.get()) ) {
    169116                        if ( const ast::EnumDecl * decl = inst->base ) {
     
    181128                const std::string & fname = function->name;
    182129                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;
    189137                        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                }
    248152                // TODO: implement other intrinsic functions
    249153        }
    250154};
    251155
    252 std::pair<long long int, bool> eval( const Expression * expr ) {
     156std::pair<long long int, bool> eval( const Expression * expr) {
    253157        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);
    257161        } else {
    258                 return std::make_pair( 0, false );
     162                return std::make_pair(0, false);
    259163        }
    260164}
    261165
    262 std::pair<long long int, bool> eval( const ast::Expr * expr ) {
     166std::pair<long long int, bool> eval(const ast::Expr * expr) {
    263167        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);
    267171        } else {
    268                 return std::make_pair( 0, false );
     172                return std::make_pair(0, false);
    269173        }
    270174}
Note: See TracChangeset for help on using the changeset viewer.