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 // static
    156 ConstantExpression ConstantExpression::Zero(ScalarType::Kind kind) {
    157     ConstantExpression ce = ValueOf(kind, 0);
    158     ce.mExpr = "0";
    159     return ce;
    160 }
    161 
    162 // static
    163 ConstantExpression ConstantExpression::One(ScalarType::Kind kind) {
    164     ConstantExpression ce = ValueOf(kind, 1);
    165     ce.mExpr = "1";
    166     return ce;
    167 }
    168 
    169 // static
    170 ConstantExpression ConstantExpression::ValueOf(ScalarType::Kind kind, uint64_t value) {
    171     ConstantExpression ce;
    172     CHECK(isSupported(kind));
    173 
    174     ce.mExpr = "";
    175     ce.mType = kConstExprLiteral;
    176     ce.mValueKind = kind;
    177     ce.mValue = value;
    178     ce.mTrivialDescription = true;
    179     return ce;
    180 }
    181 ConstantExpression::ConstantExpression(const ConstantExpression& other) {
    182     *this = other;
    183 }
    184 
    185 /* Copy constructor, with the expr overriden and treated non-trivial */
    186 ConstantExpression::ConstantExpression(const ConstantExpression& other, std::string expr) {
    187     *this = other;
    188     mExpr = expr;
    189     mTrivialDescription = false;
    190 }
    191 
    192 ConstantExpression& ConstantExpression::operator=(const ConstantExpression& other) {
    193     mType = other.mType;
    194     mValueKind = other.mValueKind;
    195     mValue = other.mValue;
    196     mExpr = other.mExpr;
    197     mTrivialDescription = other.mTrivialDescription;
    198     return *this;
    199 }
    200 
    201 /* Literals. */
    202 ConstantExpression::ConstantExpression(const char *value)
    203         : mExpr(value), mType(kConstExprLiteral), mTrivialDescription(true) {
    204     const char* head = value, *tail = head + strlen(value) - 1;
    205     bool isLong = false, isUnsigned = false;
    206     bool isHex = (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'));
    207     while(tail >= head && (*tail == 'u' || *tail == 'U' || *tail == 'l' || *tail == 'L')) {
    208         isUnsigned |= (*tail == 'u' || *tail == 'U');
    209         isLong     |= (*tail == 'l' || *tail == 'L');
    210         tail--;
    211     }
    212     char *newVal = strndup(value, tail - head + 1);
    213     bool parseOK = base::ParseUint(newVal, &mValue);
    214     free(newVal);
    215     CHECK(parseOK) << "Could not parse as integer: " << value;
    216 
    217     // guess literal type.
    218     if(isLong) {
    219         if(isUnsigned) // ul
    220             mValueKind = SK(UINT64);
    221         else // l
    222             mValueKind = SK(INT64);
    223     } else { // no l suffix
    224         if(isUnsigned) { // u
    225             if(mValue <= UINT32_MAX)
    226                 mValueKind = SK(UINT32);
    227             else
    228                 mValueKind = SK(UINT64);
    229         } else { // no suffix
    230             if(isHex) {
    231                 if(mValue <= INT32_MAX) // mValue always >= 0
    232                     mValueKind = SK(INT32);
    233                 else if(mValue <= UINT32_MAX)
    234                     mValueKind = SK(UINT32);
    235                 else if(mValue <= INT64_MAX) // mValue always >= 0
    236                     mValueKind = SK(INT64);
    237                 else if(mValue <= UINT64_MAX)
    238                     mValueKind = SK(UINT64);
    239             } else {
    240                 if(mValue <= INT32_MAX) // mValue always >= 0
    241                     mValueKind = SK(INT32);
    242                 else
    243                     mValueKind = SK(INT64);
    244             }
    245         }
    246     }
    247 }
    248 
    249 /* Unary operations. */
    250 ConstantExpression::ConstantExpression(const char *op,
    251                                        const ConstantExpression *value)
    252         : mExpr(std::string("(") + op + value->mExpr + ")"),
    253           mType(kConstExprUnary),
    254           mValueKind(value->mValueKind) {
    255 
    256 #define CASE_UNARY(__type__)\
    257             mValue = handleUnary(op, static_cast<__type__>(value->mValue)); return;
    258 
    259     SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
    260 }
    261 
    262 /* Binary operations. */
    263 ConstantExpression::ConstantExpression(const ConstantExpression *lval,
    264                                        const char *op,
    265                                        const ConstantExpression* rval)
    266         : mExpr(std::string("(") + lval->mExpr + " " + op + " " + rval->mExpr + ")"),
    267           mType(kConstExprBinary)
    268 {
    269 
    270     bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
    271 
    272     // CASE 1: + - *  / % | ^ & < > <= >= == !=
    273     if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
    274         // promoted kind for both operands.
    275         ScalarType::Kind promoted = usualArithmeticConversion(
    276                 integralPromotion(lval->mValueKind),
    277                 integralPromotion(rval->mValueKind));
    278         // result kind.
    279         mValueKind = isArithmeticOrBitflip
    280                     ? promoted // arithmetic or bitflip operators generates promoted type
    281                     : SK(BOOL); // comparison operators generates bool
    282 
    283 #define CASE_BINARY_COMMON(__type__)\
    284             mValue = handleBinaryCommon(static_cast<__type__>(lval->mValue), op, static_cast<__type__>(rval->mValue)); return;
    285 
    286         SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
    287     }
    288 
    289     // CASE 2: << >>
    290     if(OP_IS_BIN_SHIFT) {
    291         mValueKind = integralPromotion(lval->mValueKind);
    292         // instead of promoting rval, simply casting it to int64 should also be good.
    293         int64_t numBits = rval->cast<int64_t>();
    294         if(numBits < 0) {
    295             // shifting with negative number of bits is undefined in C. In HIDL it
    296             // is defined as shifting into the other direction.
    297             op = OPEQ("<<") ? ">>" : "<<";
    298             numBits = -numBits;
    299         }
    300 
    301 #define CASE_SHIFT(__type__)\
    302             mValue = handleShift(static_cast<__type__>(lval->mValue), op, numBits); return;
    303 
    304         SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
    305     }
    306 
    307     // CASE 3: && ||
    308     if(OP_IS_BIN_LOGICAL) {
    309         mValueKind = SK(BOOL);
    310         // easy; everything is bool.
    311         mValue = handleLogical(lval->mValue, op, rval->mValue);
    312         return;
    313     }
    314 
    315     SHOULD_NOT_REACH();
    316 }
    317 
    318 /* Ternary ?: operation. */
    319 ConstantExpression::ConstantExpression(const ConstantExpression *cond,
    320                                        const ConstantExpression *trueVal,
    321                                        const ConstantExpression *falseVal)
    322         : mExpr(std::string("(") + cond->mExpr + "?" + trueVal->mExpr
    323                 + ":" + falseVal->mExpr + ")"),
    324           mType(kConstExprTernary) {
    325 
    326     // note: for ?:, unlike arithmetic ops, integral promotion is not necessary.
    327     mValueKind = usualArithmeticConversion(trueVal->mValueKind,
    328                                            falseVal->mValueKind);
    329 
    330 #define CASE_TERNARY(__type__)\
    331         mValue = cond->mValue ? (static_cast<__type__>(trueVal->mValue)) : (static_cast<__type__>(falseVal->mValue)); return;
    332 
    333     SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
    334 }
    335 
    336 ConstantExpression ConstantExpression::addOne() const {
    337     ConstantExpression myOne = ConstantExpression::One(mValueKind);
    338     return ConstantExpression(this, "+", &myOne).toLiteral();
    339 }
    340 
    341 ConstantExpression &ConstantExpression::toLiteral() {
    342     mExpr = value();
    343     mType = kConstExprLiteral;
    344     return *this;
    345 }
    346 
    347 const std::string &ConstantExpression::description() const {
    348     return mExpr;
    349 }
    350 
    351 bool ConstantExpression::descriptionIsTrivial() const {
    352     return mTrivialDescription;
    353 }
    354 
    355 std::string ConstantExpression::value() const {
    356     return rawValue(mValueKind);
    357 }
    358 
    359 std::string ConstantExpression::value(ScalarType::Kind castKind) const {
    360     return rawValue(castKind);
    361 }
    362 
    363 std::string ConstantExpression::cppValue() const {
    364     return cppValue(mValueKind);
    365 }
    366 
    367 std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
    368     std::string literal(rawValue(castKind));
    369     // this is a hack to translate
    370     //       enum x : int64_t {  y = 1l << 63 };
    371     // into
    372     //       enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
    373     // by adding the explicit cast.
    374     // Because 9223372036854775808 is uint64_t, and
    375     // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
    376     // be narrowed to int64_t.
    377     if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
    378         return strdup(("static_cast<"
    379             + ScalarType(SK(INT64)).getCppStackType() // "int64_t"
    380             + ">(" + literal + "ull)").c_str());
    381     }
    382 
    383     // add suffix if necessary.
    384     if(castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
    385     if(castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
    386     return literal;
    387 }
    388 
    389 std::string ConstantExpression::javaValue() const {
    390     return javaValue(mValueKind);
    391 }
    392 
    393 std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
    394     switch(castKind) {
    395         case SK(UINT64): return rawValue(SK(INT64)) + "L";
    396         case SK(INT64):  return rawValue(SK(INT64)) + "L";
    397         case SK(UINT32): return rawValue(SK(INT32));
    398         case SK(UINT16): return rawValue(SK(INT16));
    399         case SK(UINT8) : return rawValue(SK(INT8));
    400         case SK(BOOL)  :
    401             return this->cast<bool>() ? strdup("true") : strdup("false");
    402         default: break;
    403     }
    404     return rawValue(castKind);
    405 }
    406 
    407 std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
    408 
    409 #define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
    410 
    411     SWITCH_KIND(castKind, CASE_STR, SHOULD_NOT_REACH(); return 0; );
    412 }
    413 
    414 template<typename T>
    415 T ConstantExpression::cast() const {
    416 
    417 #define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
    418 
    419     SWITCH_KIND(mValueKind, CASE_CAST_T, SHOULD_NOT_REACH(); return 0; );
    420 }
    421 
    422 size_t ConstantExpression::castSizeT() const {
    423     return this->cast<size_t>();
    424 }
    425 
    426 /*
    427 
    428 Evaluating expressions in HIDL language
    429 
    430 The following rules are mostly like that in:
    431 http://en.cppreference.com/w/cpp/language/operator_arithmetic
    432 http://en.cppreference.com/w/cpp/language/operator_logical
    433 http://en.cppreference.com/w/cpp/language/operator_comparison
    434 http://en.cppreference.com/w/cpp/language/operator_other
    435 
    436 The type of literal is the first type which the value
    437 can fit from the list of types depending on the suffix and bases.
    438 
    439 suffix              decimal bases           hexadecimal bases
    440 no suffix           int32_t                 int32_t
    441                     int64_t                 uint32_t
    442                                             int64_t
    443                                             uint64_t
    444 
    445 u/U                 uint32_t                (same as left)
    446                     uint64_t
    447 
    448 l/L                 int64_t                 int64_t
    449 
    450 ul/UL/uL/Ul         uint64_t                uint64_t
    451 
    452 
    453 Note: There are no negative integer literals.
    454       -1 is the unary minus applied to 1.
    455 
    456 Unary arithmetic and bitwise operators (~ + -):
    457   don't change the type of the argument.
    458   (so -1u = -(1u) has type uint32_t)
    459 
    460 Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
    461 1. Integral promotion is first applied on both sides.
    462 2. If both operands have the same type, no promotion is necessary.
    463 3. Usual arithmetic conversions.
    464 
    465 Integral promotion: if an operand is of a type with less than 32 bits,
    466 (including bool), it is promoted to int32_t.
    467 
    468 Usual arithmetic conversions:
    469 1. If operands are both signed or both unsigned, lesser conversion rank is
    470    converted to greater conversion rank.
    471 2. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
    472 3. Otherwise, if signed's type can hold all values in unsigned's type,
    473    -> signed's type
    474 4. Otherwise, both converted to the unsigned counterpart of the signed operand's
    475    type.
    476 rank: bool < int8_t < int16_t < int32_t < int64_t
    477 
    478 
    479 Shift operators (<< >>):
    480 1. Integral promotion is applied on both sides.
    481 2. For unsigned a, a << b discards bits that shifts out.
    482    For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
    483    For signed negative a, a << b gives error.
    484 3. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
    485    For signed negative a, a >> b discards bits that shifts out, and the signed
    486    bit gets extended. ("arithmetic right shift")
    487 4. Shifting with negative number of bits is undefined. (Currently, the
    488    parser will shift into the other direction. This behavior may change.)
    489 5. Shifting with number of bits exceeding the width of the type is undefined.
    490    (Currently, 1 << 32 == 1. This behavior may change.)
    491 
    492 Logical operators (!, &&, ||):
    493 1. Convert first operand to bool. (true if non-zero, false otherwise)
    494 2. If short-circuited, return the result as type bool, value 1 or 0.
    495 3. Otherwise, convert second operand to bool, evaluate the result, and return
    496    the result in the same fashion.
    497 
    498 Arithmetic comparison operators (< > <= >= == !=):
    499 1. Promote operands in the same way as binary arithmetic and bitwise operators.
    500    (Integral promotion + Usual arithmetic conversions)
    501 2. Return type bool, value 0 or 1 the same way as logical operators.
    502 
    503 Ternary conditional operator (?:):
    504 1. Evaluate the conditional and evaluate the operands.
    505 2. Return type of expression is the type under usual arithmetic conversions on
    506    the second and third operand. (No integral promotions necessary.)
    507 
    508 */
    509 
    510 }  // namespace android
    511 
    512