Ignore:
Timestamp:
Jan 7, 2021, 2:55:57 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
58fe85a
Parents:
bdfc032 (diff), 44e37ef (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' into dkobets-vector

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Parser/ExpressionNode.cc

    rbdfc032 reef8dfb  
    1010// Created On       : Sat May 16 13:17:07 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Dec 18 21:14:58 2019
    13 // Update Count     : 981
     12// Last Modified On : Thu Aug 20 14:01:46 2020
     13// Update Count     : 1076
    1414//
    1515
     
    6565
    6666void lnthSuffix( string & str, int & type, int & ltype ) {
     67        // 'u' can appear before or after length suffix
    6768        string::size_type posn = str.find_last_of( "lL" );
    6869
    6970        if ( posn == string::npos ) return;                                     // no suffix
    70         if ( posn == str.length() - 1 ) { type = 3; return; } // no length => long
    71 
     71        size_t end = str.length() - 1;
     72        if ( posn == end ) { type = 3; return; }                        // no length after 'l' => long
     73       
    7274        string::size_type next = posn + 1;                                      // advance to length
    7375        if ( str[next] == '3' ) {                                                       // 32
     
    8486                } // if
    8587        } // if
    86         // remove "lL" for these cases because it may not imply long
    87         str.erase( posn );                                                                      // remove length
     88
     89        char fix = '\0';
     90        if ( str[end] == 'u' || str[end] == 'U' ) fix = str[end]; // ends with 'uU' ?
     91        str.erase( posn );                                                                      // remove length suffix and possibly uU
     92        if ( type == 5 ) {                                                                      // L128 does not need uU
     93                end = str.length() - 1;
     94                if ( str[end] == 'u' || str[end] == 'U' ) str.erase( end ); // ends with 'uU' ? remove
     95        } else if ( fix != '\0' ) str += fix;                           // put 'uU' back if removed
    8896} // lnthSuffix
    8997
     
    108116} // valueToType
    109117
     118static void scanbin( string & str, unsigned long long int & v ) {
     119        v = 0;
     120        size_t last = str.length() - 1;                                         // last subscript of constant
     121        for ( unsigned int i = 2;; ) {                                          // ignore prefix
     122                if ( str[i] == '1' ) v |= 1;
     123                i += 1;
     124          if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break;
     125                v <<= 1;
     126        } // for
     127} // scanbin
     128
    110129Expression * build_constantInteger( string & str ) {
    111130        static const BasicType::Kind kind[2][6] = {
    112131                // short (h) must be before char (hh) because shorter type has the longer suffix
    113                 { BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, BasicType::SignedInt128, },
    114                 { BasicType::ShortUnsignedInt, BasicType::UnsignedChar, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::UnsignedInt128, },
     132                { BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, /* BasicType::SignedInt128 */ BasicType::LongLongSignedInt, },
     133                { BasicType::ShortUnsignedInt, BasicType::UnsignedChar, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, /* BasicType::UnsignedInt128 */ BasicType::LongLongUnsignedInt, },
    115134        };
    116135
     
    120139        }; // lnthsInt
    121140
    122         unsigned long long int v;                                                       // converted integral value
    123         size_t last = str.length() - 1;                                         // last subscript of constant
    124         Expression * ret;
    125         //string fred( str );
     141        string str2( "0x0" );
     142        unsigned long long int v, v2 = 0;                                       // converted integral value
     143        Expression * ret, * ret2;
    126144
    127145        int type = -1;                                                                          // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128
     
    139157        } // if
    140158
     159        string::size_type posn;
     160
     161        // 'u' can appear before or after length suffix
     162        if ( str.find_last_of( "uU" ) != string::npos ) Unsigned = true;
     163
     164        if ( isdigit( str[str.length() - 1] ) ) {                       // no suffix ?
     165                lnthSuffix( str, type, ltype );                                 // could have length suffix
     166        } else {
     167                // At least one digit in integer constant, so safe to backup while looking for suffix.
     168
     169                posn = str.find_last_of( "pP" );                                // pointer value
     170                if ( posn != string::npos ) { ltype = 5; str.erase( posn, 1 ); goto FINI; }
     171
     172                posn = str.find_last_of( "zZ" );                                // size_t
     173                if ( posn != string::npos ) { Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); goto FINI; }
     174
     175                posn = str.rfind( "hh" );                                               // char
     176                if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; }
     177
     178                posn = str.rfind( "HH" );                                               // char
     179                if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; }
     180
     181                posn = str.find_last_of( "hH" );                                // short
     182                if ( posn != string::npos ) { type = 0; str.erase( posn, 1 ); goto FINI; }
     183
     184                posn = str.find_last_of( "nN" );                                // int (natural number)
     185                if ( posn != string::npos ) { type = 2; str.erase( posn, 1 ); goto FINI; }
     186
     187                if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) { type = 4; goto FINI; }
     188
     189                lnthSuffix( str, type, ltype );                                 // must be after check for "ll"
     190          FINI: ;
     191        } // if
     192
    141193        // Cannot be just "0"/"1"; sscanf stops at the suffix, if any; value goes over the wall => always generate
    142194
     195#if ! defined(__SIZEOF_INT128__)
     196        if ( type == 5 ) SemanticError( yylloc, "int128 constant is not supported on this target " + str );
     197#endif // ! __SIZEOF_INT128__
     198       
    143199        if ( str[0] == '0' ) {                                                          // radix character ?
    144200                dec = false;
    145201                if ( checkX( str[1] ) ) {                                               // hex constant ?
    146                         sscanf( (char *)str.c_str(), "%llx", &v );
     202                        if ( type < 5 ) {                                                       // not L128 ?
     203                                sscanf( (char *)str.c_str(), "%llx", &v );
     204#if defined(__SIZEOF_INT128__)
     205                        } else {                                                                        // hex int128 constant
     206                                unsigned int len = str.length();
     207                                if ( len > (2 + 16 + 16) ) SemanticError( yylloc, "128-bit hexadecimal constant to large " + str );
     208                          if ( len <= (2 + 16) ) goto FHEX1;            // hex digits < 2^64
     209                                str2 = "0x" + str.substr( len - 16 );
     210                                sscanf( (char *)str2.c_str(), "%llx", &v2 );
     211                                str = str.substr( 0, len - 16 );
     212                          FHEX1: ;
     213                                sscanf( (char *)str.c_str(), "%llx", &v );
     214#endif // __SIZEOF_INT128__
     215                        } // if
    147216                        //printf( "%llx %llu\n", v, v );
    148217                } else if ( checkB( str[1] ) ) {                                // binary constant ?
    149                         v = 0;                                                                          // compute value
    150                         for ( unsigned int i = 2;; ) {                          // ignore prefix
    151                                 if ( str[i] == '1' ) v |= 1;
    152                                 i += 1;
    153                           if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break;
    154                                 v <<= 1;
    155                         } // for
     218#if defined(__SIZEOF_INT128__)
     219                        unsigned int len = str.length();
     220                        if ( type == 5 && len > 2 + 64 ) {
     221                                if ( len > 2 + 64 + 64 ) SemanticError( yylloc, "128-bit binary constant to large " + str );
     222                                str2 = "0b" + str.substr( len - 64 );
     223                                str = str.substr( 0, len - 64 );
     224                                scanbin( str2, v2 );
     225                        } // if
     226#endif // __SIZEOF_INT128__
     227                        scanbin( str, v );
    156228                        //printf( "%#llx %llu\n", v, v );
    157229                } else {                                                                                // octal constant
    158                         sscanf( (char *)str.c_str(), "%llo", &v );
     230                        if ( type < 5 ) {                                                       // not L128 ?
     231                                sscanf( (char *)str.c_str(), "%llo", &v );
     232#if defined(__SIZEOF_INT128__)
     233                        } else {                                                                        // octal int128 constant
     234                                unsigned int len = str.length();
     235                                if ( len > 1 + 43 || (len == 1 + 43 && str[0] > '3') ) SemanticError( yylloc, "128-bit octal constant to large " + str );
     236                                char buf[32];
     237                                if ( len <= 1 + 21 ) {                                  // value < 21 octal digitis
     238                                        sscanf( (char *)str.c_str(), "%llo", &v );
     239                                } else {
     240                                        sscanf( &str[len - 21], "%llo", &v );
     241                                        __int128 val = v;                                       // accumulate bits
     242                                        str[len - 21] ='\0';                            // shorten string
     243                                        sscanf( &str[len == 43 ? 1 : 0], "%llo", &v );
     244                                        val |= (__int128)v << 63;                       // store bits
     245                                        if ( len == 1 + 43 ) {                          // most significant 2 bits ?
     246                                                str[2] = '\0';                                  // shorten string
     247                                                sscanf( &str[1], "%llo", &v );  // process most significant 2 bits
     248                                                val |= (__int128)v << 126;              // store bits
     249                                        } // if
     250                                        v = val >> 64; v2 = (uint64_t)val;      // replace octal constant with 2 hex constants
     251                                        sprintf( buf, "%#llx", v2 );
     252                                        str2 = buf;
     253                                } // if
     254                                sprintf( buf, "%#llx", v );
     255                                str = buf;
     256#endif // __SIZEOF_INT128__
     257                        } // if
    159258                        //printf( "%#llo %llu\n", v, v );
    160259                } // if
    161260        } else {                                                                                        // decimal constant ?
    162                 sscanf( (char *)str.c_str(), "%llu", &v );
     261                if ( type < 5 ) {                                                               // not L128 ?
     262                        sscanf( (char *)str.c_str(), "%llu", &v );
     263#if defined(__SIZEOF_INT128__)
     264                } else {                                                                                // decimal int128 constant
     265                        #define P10_UINT64 10'000'000'000'000'000'000ULL // 19 zeroes
     266                        unsigned int len = str.length();
     267                        if ( str.length() == 39 && str > (Unsigned ? "340282366920938463463374607431768211455" : "170141183460469231731687303715884105727") )
     268                                SemanticError( yylloc, "128-bit decimal constant to large " + str );
     269                        char buf[32];
     270                        if ( len <= 19 ) {                                                      // value < 19 decimal digitis
     271                                sscanf( (char *)str.c_str(), "%llu", &v );
     272                        } else {
     273                                sscanf( &str[len - 19], "%llu", &v );
     274                                __int128 val = v;                                               // accumulate bits
     275                                str[len - 19] ='\0';                                    // shorten string
     276                                sscanf( &str[len == 39 ? 1 : 0], "%llu", &v );
     277                                val += (__int128)v * (__int128)P10_UINT64; // store bits
     278                                if ( len == 39 ) {                                              // most significant 2 bits ?
     279                                        str[1] = '\0';                                          // shorten string
     280                                        sscanf( &str[0], "%llu", &v );          // process most significant 2 bits
     281                                        val += (__int128)v * (__int128)P10_UINT64 * (__int128)P10_UINT64; // store bits
     282                                } // if
     283                                v = val >> 64; v2 = (uint64_t)val;              // replace decimal constant with 2 hex constants
     284                                sprintf( buf, "%#llx", v2 );
     285                                str2 = buf;
     286                        } // if
     287                        sprintf( buf, "%#llx", v );
     288                        str = buf;
     289#endif // __SIZEOF_INT128__
     290                } // if
    163291                //printf( "%llu\n", v );
    164292        } // if
    165293
    166         string::size_type posn;
    167 
    168         if ( isdigit( str[last] ) ) {                                           // no suffix ?
    169                 lnthSuffix( str, type, ltype );                                 // could have length suffix
    170                 if ( type == -1 ) {                                                             // no suffix
    171                         valueToType( v, dec, type, Unsigned );
    172                 } // if
    173         } else {
    174                 // At least one digit in integer constant, so safe to backup while looking for suffix.
    175 
    176                 posn = str.find_last_of( "pP" );
    177                 if ( posn != string::npos ) { valueToType( v, dec, type, Unsigned ); ltype = 5; str.erase( posn, 1 ); goto FINI; }
    178 
    179                 posn = str.find_last_of( "zZ" );
    180                 if ( posn != string::npos ) { Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); goto FINI; }
    181 
    182                 // 'u' can appear before or after length suffix
    183                 if ( str.find_last_of( "uU" ) != string::npos ) Unsigned = true;
    184 
    185                 posn = str.rfind( "hh" );
    186                 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; }
    187 
    188                 posn = str.rfind( "HH" );
    189                 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; }
    190 
    191                 posn = str.find_last_of( "hH" );
    192                 if ( posn != string::npos ) { type = 0; str.erase( posn, 1 ); goto FINI; }
    193 
    194                 posn = str.find_last_of( "nN" );
    195                 if ( posn != string::npos ) { type = 2; str.erase( posn, 1 ); goto FINI; }
    196 
    197                 if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) { type = 4; goto FINI; }
    198 
    199                 lnthSuffix( str, type, ltype );                                 // must be after check for "ll"
    200                 if ( type == -1 ) {                                                             // only 'u' suffix ?
    201                         valueToType( v, dec, type, Unsigned );
    202                 } // if
    203           FINI: ;
    204         } // if
     294        if ( type == -1 ) {                                                                     // no suffix => determine type from value size
     295                valueToType( v, dec, type, Unsigned );
     296        } // if
     297        /* printf( "%s %llo %s %llo\n", str.c_str(), v, str2.c_str(), v2 ); */
    205298
    206299        //if ( !( 0 <= type && type <= 6 ) ) { printf( "%s %lu %d %s\n", fred.c_str(), fred.length(), type, str.c_str() ); }
     
    214307        } else if ( ltype != -1 ) {                                                     // explicit length ?
    215308                if ( ltype == 6 ) {                                                             // int128, (int128)constant
    216                         ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false );
     309//                      ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false );
     310                        ret2 = new ConstantExpr( Constant( new BasicType( noQualifiers, BasicType::LongLongSignedInt ), str2, v2 ) );
     311                        ret = build_compoundLiteral( DeclarationNode::newBasicType( DeclarationNode::Int128 )->addType( DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ),
     312                                                                                 new InitializerNode( (InitializerNode *)(new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true ) );
    217313                } else {                                                                                // explicit length, (length_type)constant
    218314                        ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), lnthsInt[Unsigned][ltype], false ), false );
     
    342438                if ( str[1] == '8' ) goto Default;                              // utf-8 characters => array of char
    343439                // lookup type of associated typedef
    344                 strtype = new TypeInstType( Type::Qualifiers( Type::Const ), "char16_t", false );
     440                strtype = new TypeInstType( Type::Qualifiers( ), "char16_t", false );
    345441                break;
    346442          case 'U':
    347                 strtype = new TypeInstType( Type::Qualifiers( Type::Const ), "char32_t", false );
     443                strtype = new TypeInstType( Type::Qualifiers( ), "char32_t", false );
    348444                break;
    349445          case 'L':
    350                 strtype = new TypeInstType( Type::Qualifiers( Type::Const ), "wchar_t", false );
     446                strtype = new TypeInstType( Type::Qualifiers( ), "wchar_t", false );
    351447                break;
    352448          Default:                                                                                      // char default string type
    353449          default:
    354                 strtype = new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char );
     450                strtype = new BasicType( Type::Qualifiers( ), BasicType::Char );
    355451        } // switch
    356452        ArrayType * at = new ArrayType( noQualifiers, strtype,
Note: See TracChangeset for help on using the changeset viewer.