Home | History | Annotate | Download | only in hidl
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "ConstantExpression.h"
     18 
     19 #include <stdio.h>
     20 #include <string>
     21 #include <android-base/parseint.h>
     22 #include <android-base/logging.h>
     23 #include <sstream>
     24 
     25 #include "EnumType.h"
     26 
     27 // The macros are really nasty here. Consider removing
     28 // as many macros as possible.
     29 
     30 #define STREQ(__x__, __y__) (strcmp((__x__), (__y__)) == 0)
     31 #define OPEQ(__y__) STREQ(op, __y__)
     32 #define COMPUTE_UNARY(__op__)  if(OPEQ(#__op__)) return __op__ val;
     33 #define COMPUTE_BINARY(__op__) if(OPEQ(#__op__)) return lval __op__ rval;
     34 #define OP_IS_BIN_ARITHMETIC  (OPEQ("+") || OPEQ("-") || OPEQ("*") || OPEQ("/") || OPEQ("%"))
     35 #define OP_IS_BIN_BITFLIP     (OPEQ("|") || OPEQ("^") || OPEQ("&"))
     36 #define OP_IS_BIN_COMP        (OPEQ("<") || OPEQ(">") || OPEQ("<=") || OPEQ(">=") || OPEQ("==") || OPEQ("!="))
     37 #define OP_IS_BIN_SHIFT       (OPEQ(">>") || OPEQ("<<"))
     38 #define OP_IS_BIN_LOGICAL     (OPEQ("||") || OPEQ("&&"))
     39 #define SK(__x__) ScalarType::Kind::KIND_##__x__
     40 #define SHOULD_NOT_REACH() CHECK(false) << __LINE__ << ": should not reach here: "
     41 
     42 #define SWITCH_KIND(__cond__, __action__, __def__)           \
     43         switch(__cond__) {                                        \
     44             case SK(BOOL): __action__(bool)                         \
     45             case SK(UINT8): __action__(uint8_t)                     \
     46             case SK(INT8): __action__(int8_t)                       \
     47             case SK(UINT16): __action__(uint16_t)                   \
     48             case SK(INT16): __action__(int16_t)                     \
     49             case SK(UINT32): __action__(uint32_t)                   \
     50             case SK(INT32): __action__(int32_t)                     \
     51             case SK(UINT64): __action__(uint64_t)                   \
     52             case SK(INT64): __action__(int64_t)                     \
     53             default: __def__                                        \
     54         }                                                         \
     55 
     56 namespace android {
     57 
     58 static inline bool isSupported(ScalarType::Kind kind) {
     59     return SK(BOOL) == kind || ScalarType(kind).isValidEnumStorageType();
     60 }
     61 
     62 /* See docs at the end for details on integral promotion. */
     63 ScalarType::Kind integralPromotion(ScalarType::Kind in) {
     64     return SK(INT32) < in ? in : SK(INT32); // note that KIND_INT32 < KIND_UINT32
     65 }
     66 
     67 /* See docs at the end for details on usual arithmetic conversion. */
     68 ScalarType::Kind usualArithmeticConversion(ScalarType::Kind lft,
     69                                            ScalarType::Kind rgt) {
     70     CHECK(isSupported(lft) && isSupported(rgt));
     71     // Kinds in concern: bool, (u)int[8|16|32|64]
     72     if(lft == rgt) return lft; // easy case
     73     if(lft == SK(BOOL)) return rgt;
     74     if(rgt == SK(BOOL)) return lft;
     75     bool isLftSigned = (lft == SK(INT8))  || (lft == SK(INT16))
     76                     || (lft == SK(INT32)) || (lft == SK(INT64));
     77     bool isRgtSigned = (rgt == SK(INT8))  || (rgt == SK(INT16))
     78                     || (rgt == SK(INT32)) || (rgt == SK(INT64));
     79     if(isLftSigned == isRgtSigned) return lft < rgt ? rgt : lft;
     80     ScalarType::Kind unsignedRank = isLftSigned ? rgt : lft;
     81     ScalarType::Kind signedRank   = isLftSigned ? lft : rgt;
     82     if(unsignedRank >= signedRank) return unsignedRank;
     83     if(signedRank > unsignedRank)  return signedRank;
     84 
     85     // Although there is such rule to return "the unsigned counterpart of
     86     // the signed operand", it should not reach here in our HIDL grammar.
     87     LOG(FATAL) << "Could not do usual arithmetic conversion for type "
     88                << lft << "and" << rgt;
     89     switch(signedRank) {
     90         case SK(INT8):  return SK(UINT8);
     91         case SK(INT16): return SK(UINT16);
     92         case SK(INT32): return SK(UINT32);
     93         case SK(INT64): return SK(UINT64);
     94         default: return SK(UINT64);
     95     }
     96 }
     97 
     98 template <class T>
     99 T handleUnary(const char *op, T val) {
    100     COMPUTE_UNARY(+)
    101     COMPUTE_UNARY(-)
    102     COMPUTE_UNARY(!)
    103     COMPUTE_UNARY(~)
    104     // Should not reach here.
    105     SHOULD_NOT_REACH() << "Could not handleUnary for " << op << " " << val;
    106     return static_cast<T>(0xdeadbeef);
    107 }
    108 
    109 template <class T>
    110 T handleBinaryCommon(T lval, const char *op, T rval) {
    111     COMPUTE_BINARY(+)
    112     COMPUTE_BINARY(-)
    113     COMPUTE_BINARY(*)
    114     COMPUTE_BINARY(/)
    115     COMPUTE_BINARY(%)
    116     COMPUTE_BINARY(|)
    117     COMPUTE_BINARY(^)
    118     COMPUTE_BINARY(&)
    119     // comparison operators: return 0 or 1 by nature.
    120     COMPUTE_BINARY(==)
    121     COMPUTE_BINARY(!=)
    122     COMPUTE_BINARY(<)
    123     COMPUTE_BINARY(>)
    124     COMPUTE_BINARY(<=)
    125     COMPUTE_BINARY(>=)
    126     // Should not reach here.
    127     SHOULD_NOT_REACH() << "Could not handleBinaryCommon for "
    128                        << lval << " " << op << " " << rval;
    129     return static_cast<T>(0xdeadbeef);
    130 }
    131 
    132 template <class T>
    133 T handleShift(T lval, const char *op, int64_t rval) {
    134     // just cast rval to int64_t and it should fit.
    135     COMPUTE_BINARY(>>)
    136     COMPUTE_BINARY(<<)
    137     // Should not reach here.
    138     SHOULD_NOT_REACH() << "Could not handleShift for"
    139                        << lval << " " << op << " " << rval;
    140     return static_cast<T>(0xdeadbeef);
    141 }
    142 
    143 bool handleLogical(bool lval, const char *op, bool rval) {
    144     COMPUTE_BINARY(||);
    145     COMPUTE_BINARY(&&);
    146     // Should not reach here.
    147     SHOULD_NOT_REACH() << "Could not handleLogical for"
    148                        << lval << " " << op << " " << rval;
    149     return false;
    150 }
    151 
    152 ConstantExpression::ConstantExpression() {
    153 }
    154 
    155 ConstantExpression ConstantExpression::Zero(ScalarType::Kind kind) {
    156     ConstantExpression ce = ValueOf(kind, 0);
    157     ce.mExpr = "0";
    158     return ce;
    159 }
    160 
    161 ConstantExpression ConstantExpression::One(ScalarType::Kind kind) {
    162     ConstantExpression ce = ValueOf(kind, 1);
    163     ce.mExpr = "1";
    164     return ce;
    165 }
    166 
    167 ConstantExpression ConstantExpression::ValueOf(ScalarType::Kind kind, uint64_t value) {
    168     ConstantExpression ce;
    169     CHECK(isSupported(kind));
    170 
    171     ce.mExpr = "";
    172     ce.mType = kConstExprLiteral;
    173     ce.mValueKind = kind;
    174     ce.mValue = value;
    175     ce.mTrivialDescription = true;
    176     return ce;
    177 }
    178 ConstantExpression::ConstantExpression(const ConstantExpression& other) {
    179     *this = other;
    180 }
    181 
    182 /* Copy constructor, with the expr overriden and treated non-trivial */
    183 ConstantExpression::ConstantExpression(const ConstantExpression& other, std::string expr) {
    184     *this = other;
    185     mExpr = expr;
    186     mTrivialDescription = false;
    187 }
    188 
    189 ConstantExpression& ConstantExpression::operator=(const ConstantExpression& other) {
    190     mType = other.mType;
    191     mValueKind = other.mValueKind;
    192     mValue = other.mValue;
    193     mExpr = other.mExpr;
    194     mTrivialDescription = other.mTrivialDescription;
    195     return *this;
    196 }
    197 
    198 /* Literals. */
    199 ConstantExpression::ConstantExpression(const char *value)
    200         : mExpr(value), mType(kConstExprLiteral), mTrivialDescription(true) {
    201     const char* head = value, *tail = head + strlen(value) - 1;
    202     bool isLong = false, isUnsigned = false;
    203     bool isHex = (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'));
    204     while(tail >= head && (*tail == 'u' || *tail == 'U' || *tail == 'l' || *tail == 'L')) {
    205         isUnsigned |= (*tail == 'u' || *tail == 'U');
    206         isLong     |= (*tail == 'l' || *tail == 'L');
    207         tail--;
    208     }
    209     char *newVal = strndup(value, tail - head + 1);
    210     bool parseOK = base::ParseUint(newVal, &mValue);
    211     free(newVal);
    212     CHECK(parseOK) << "Could not parse as integer: " << value;
    213 
    214     // guess literal type.
    215     if(isLong) {
    216         if(isUnsigned) // ul
    217             mValueKind = SK(UINT64);
    218         else // l
    219             mValueKind = SK(INT64);
    220     } else { // no l suffix
    221         if(isUnsigned) { // u
    222             if(mValue <= UINT32_MAX)
    223                 mValueKind = SK(UINT32);
    224             else
    225                 mValueKind = SK(UINT64);
    226         } else { // no suffix
    227             if(isHex) {
    228                 if(mValue <= INT32_MAX) // mValue always >= 0
    229                     mValueKind = SK(INT32);
    230                 else if(mValue <= UINT32_MAX)
    231                     mValueKind = SK(UINT32);
    232                 else if(mValue <= INT64_MAX) // mValue always >= 0
    233                     mValueKind = SK(INT64);
    234                 else if(mValue <= UINT64_MAX)
    235                     mValueKind = SK(UINT64);
    236             } else {
    237                 if(mValue <= INT32_MAX) // mValue always >= 0
    238                     mValueKind = SK(INT32);
    239                 else
    240                     mValueKind = SK(INT64);
    241             }
    242         }
    243     }
    244 }
    245 
    246 /* Unary operations. */
    247 ConstantExpression::ConstantExpression(const char *op,
    248                                        const ConstantExpression *value)
    249         : mExpr(std::string("(") + op + value->mExpr + ")"),
    250           mType(kConstExprUnary),
    251           mValueKind(value->mValueKind) {
    252 
    253 #define CASE_UNARY(__type__)\
    254             mValue = handleUnary(op, static_cast<__type__>(value->mValue)); return;
    255 
    256     SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
    257 }
    258 
    259 /* Binary operations. */
    260 ConstantExpression::ConstantExpression(const ConstantExpression *lval,
    261                                        const char *op,
    262                                        const ConstantExpression* rval)
    263         : mExpr(std::string("(") + lval->mExpr + " " + op + " " + rval->mExpr + ")"),
    264           mType(kConstExprBinary)
    265 {
    266 
    267     bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
    268 
    269     // CASE 1: + - *  / % | ^ & < > <= >= == !=
    270     if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
    271         // promoted kind for both operands.
    272         ScalarType::Kind promoted = usualArithmeticConversion(
    273                 integralPromotion(lval->mValueKind),
    274                 integralPromotion(rval->mValueKind));
    275         // result kind.
    276         mValueKind = isArithmeticOrBitflip
    277                     ? promoted // arithmetic or bitflip operators generates promoted type
    278                     : SK(BOOL); // comparison operators generates bool
    279 
    280 #define CASE_BINARY_COMMON(__type__)\
    281             mValue = handleBinaryCommon(static_cast<__type__>(lval->mValue), op, static_cast<__type__>(rval->mValue)); return;
    282 
    283         SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
    284     }
    285 
    286     // CASE 2: << >>
    287     if(OP_IS_BIN_SHIFT) {
    288         mValueKind = integralPromotion(lval->mValueKind);
    289         // instead of promoting rval, simply casting it to int64 should also be good.
    290         int64_t numBits = rval->cast<int64_t>();
    291         if(numBits < 0) {
    292             // shifting with negative number of bits is undefined in C. In HIDL it
    293             // is defined as shifting into the other direction.
    294             op = OPEQ("<<") ? ">>" : "<<";
    295             numBits = -numBits;
    296         }
    297 
    298 #define CASE_SHIFT(__type__)\
    299             mValue = handleShift(static_cast<__type__>(lval->mValue), op, numBits); return;
    300 
    301         SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
    302     }
    303 
    304     // CASE 3: && ||
    305     if(OP_IS_BIN_LOGICAL) {
    306         mValueKind = SK(BOOL);
    307         // easy; everything is bool.
    308         mValue = handleLogical(lval->mValue, op, rval->mValue);
    309         return;
    310     }
    311 
    312     SHOULD_NOT_REACH();
    313 }
    314 
    315 /* Ternary ?: operation. */
    316 ConstantExpression::ConstantExpression(const ConstantExpression *cond,
    317                                        const ConstantExpression *trueVal,
    318                                        const ConstantExpression *falseVal)
    319         : mExpr(std::string("(") + cond->mExpr + "?" + trueVal->mExpr
    320                 + ":" + falseVal->mExpr + ")"),
    321           mType(kConstExprTernary) {
    322 
    323     // note: for ?:, unlike arithmetic ops, integral promotion is not necessary.
    324     mValueKind = usualArithmeticConversion(trueVal->mValueKind,
    325                                            falseVal->mValueKind);
    326 
    327 #define CASE_TERNARY(__type__)\
    328         mValue = cond->mValue ? (static_cast<__type__>(trueVal->mValue)) : (static_cast<__type__>(falseVal->mValue)); return;
    329 
    330     SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
    331 }
    332 
    333 ConstantExpression ConstantExpression::addOne() const {
    334     ConstantExpression myOne = ConstantExpression::One(mValueKind);
    335     return ConstantExpression(this, "+", &myOne).toLiteral();
    336 }
    337 
    338 ConstantExpression &ConstantExpression::toLiteral() {
    339     mExpr = value();
    340     mType = kConstExprLiteral;
    341     return *this;
    342 }
    343 
    344 const std::string &ConstantExpression::description() const {
    345     return mExpr;
    346 }
    347 
    348 bool ConstantExpression::descriptionIsTrivial() const {
    349     return mTrivialDescription;
    350 }
    351 
    352 std::string ConstantExpression::value() const {
    353     return rawValue(mValueKind);
    354 }
    355 
    356 std::string ConstantExpression::value(ScalarType::Kind castKind) const {
    357     return rawValue(castKind);
    358 }
    359 
    360 std::string ConstantExpression::cppValue() const {
    361     return cppValue(mValueKind);
    362 }
    363 
    364 std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
    365     std::string literal(rawValue(castKind));
    366     // this is a hack to translate
    367     //       enum x : int64_t {  y = 1l << 63 };
    368     // into
    369     //       enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
    370     // by adding the explicit cast.
    371     // Because 9223372036854775808 is uint64_t, and
    372     // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
    373     // be narrowed to int64_t.
    374     if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
    375         return strdup(("static_cast<"
    376             + ScalarType(SK(INT64)).getCppStackType() // "int64_t"
    377             + ">(" + literal + "ull)").c_str());
    378     }
    379 
    380     // add suffix if necessary.
    381     if(castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
    382     if(castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
    383     return literal;
    384 }
    385 
    386 std::string ConstantExpression::javaValue() const {
    387     return javaValue(mValueKind);
    388 }
    389 
    390 std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
    391     switch(castKind) {
    392         case SK(UINT64): return rawValue(SK(INT64)) + "L";
    393         case SK(INT64):  return rawValue(SK(INT64)) + "L";
    394         case SK(UINT32): return rawValue(SK(INT32));
    395         case SK(UINT16): return rawValue(SK(INT16));
    396         case SK(UINT8) : return rawValue(SK(INT8));
    397         case SK(BOOL)  :
    398             return this->cast<bool>() ? strdup("true") : strdup("false");
    399         default: break;
    400     }
    401     return rawValue(castKind);
    402 }
    403 
    404 std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
    405 
    406 #define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
    407 
    408     SWITCH_KIND(castKind, CASE_STR, SHOULD_NOT_REACH(); return 0; );
    409 }
    410 
    411 template<typename T>
    412 T ConstantExpression::cast() const {
    413 
    414 #define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
    415 
    416     SWITCH_KIND(mValueKind, CASE_CAST_T, SHOULD_NOT_REACH(); return 0; );
    417 }
    418 
    419 size_t ConstantExpression::castSizeT() const {
    420     return this->cast<size_t>();
    421 }
    422 
    423 /*
    424 
    425 Evaluating expressions in HIDL language
    426 
    427 The following rules are mostly like that in:
    428 http://en.cppreference.com/w/cpp/language/operator_arithmetic
    429 http://en.cppreference.com/w/cpp/language/operator_logical
    430 http://en.cppreference.com/w/cpp/language/operator_comparison
    431 http://en.cppreference.com/w/cpp/language/operator_other
    432 
    433 The type of literal is the first type which the value
    434 can fit from the list of types depending on the suffix and bases.
    435 
    436 suffix              decimal bases           hexadecimal bases
    437 no suffix           int32_t                 int32_t
    438                     int64_t                 uint32_t
    439                                             int64_t
    440                                             uint64_t
    441 
    442 u/U                 uint32_t                (same as left)
    443                     uint64_t
    444 
    445 l/L                 int64_t                 int64_t
    446 
    447 ul/UL/uL/Ul         uint64_t                uint64_t
    448 
    449 
    450 Note: There are no negative integer literals.
    451       -1 is the unary minus applied to 1.
    452 
    453 Unary arithmetic and bitwise operators (~ + -):
    454   don't change the type of the argument.
    455   (so -1u = -(1u) has type uint32_t)
    456 
    457 Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
    458 1. Integral promotion is first applied on both sides.
    459 2. If both operands have the same type, no promotion is necessary.
    460 3. Usual arithmetic conversions.
    461 
    462 Integral promotion: if an operand is of a type with less than 32 bits,
    463 (including bool), it is promoted to int32_t.
    464 
    465 Usual arithmetic conversions:
    466 1. If operands are both signed or both unsigned, lesser conversion rank is
    467    converted to greater conversion rank.
    468 2. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
    469 3. Otherwise, if signed's type can hold all values in unsigned's type,
    470    -> signed's type
    471 4. Otherwise, both converted to the unsigned counterpart of the signed operand's
    472    type.
    473 rank: bool < int8_t < int16_t < int32_t < int64_t
    474 
    475 
    476 Shift operators (<< >>):
    477 1. Integral promotion is applied on both sides.
    478 2. For unsigned a, a << b discards bits that shifts out.
    479    For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
    480    For signed negative a, a << b gives error.
    481 3. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
    482    For signed negative a, a >> b discards bits that shifts out, and the signed
    483    bit gets extended. ("arithmetic right shift")
    484 4. Shifting with negative number of bits is undefined. (Currently, the
    485    parser will shift into the other direction. This behavior may change.)
    486 5. Shifting with number of bits exceeding the width of the type is undefined.
    487    (Currently, 1 << 32 == 1. This behavior may change.)
    488 
    489 Logical operators (!, &&, ||):
    490 1. Convert first operand to bool. (true if non-zero, false otherwise)
    491 2. If short-circuited, return the result as type bool, value 1 or 0.
    492 3. Otherwise, convert second operand to bool, evaluate the result, and return
    493    the result in the same fashion.
    494 
    495 Arithmetic comparison operators (< > <= >= == !=):
    496 1. Promote operands in the same way as binary arithmetic and bitwise operators.
    497    (Integral promotion + Usual arithmetic conversions)
    498 2. Return type bool, value 0 or 1 the same way as logical operators.
    499 
    500 Ternary conditional operator (?:):
    501 1. Evaluate the conditional and evaluate the operands.
    502 2. Return type of expression is the type under usual arithmetic conversions on
    503    the second and third operand. (No integral promotions necessary.)
    504 
    505 */
    506 
    507 }  // namespace android
    508 
    509