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
56namespace android {
57
58static 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. */
63ScalarType::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. */
68ScalarType::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
98template <class T>
99T 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
109template <class T>
110T 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
132template <class T>
133T 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
143bool 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
152ConstantExpression::ConstantExpression() {
153}
154
155ConstantExpression ConstantExpression::Zero(ScalarType::Kind kind) {
156    ConstantExpression ce = ValueOf(kind, 0);
157    ce.mExpr = "0";
158    return ce;
159}
160
161ConstantExpression ConstantExpression::One(ScalarType::Kind kind) {
162    ConstantExpression ce = ValueOf(kind, 1);
163    ce.mExpr = "1";
164    return ce;
165}
166
167ConstantExpression 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}
178ConstantExpression::ConstantExpression(const ConstantExpression& other) {
179    *this = other;
180}
181
182/* Copy constructor, with the expr overriden and treated non-trivial */
183ConstantExpression::ConstantExpression(const ConstantExpression& other, std::string expr) {
184    *this = other;
185    mExpr = expr;
186    mTrivialDescription = false;
187}
188
189ConstantExpression& 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. */
199ConstantExpression::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. */
247ConstantExpression::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. */
260ConstantExpression::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. */
316ConstantExpression::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
333ConstantExpression ConstantExpression::addOne() const {
334    ConstantExpression myOne = ConstantExpression::One(mValueKind);
335    return ConstantExpression(this, "+", &myOne).toLiteral();
336}
337
338ConstantExpression &ConstantExpression::toLiteral() {
339    mExpr = value();
340    mType = kConstExprLiteral;
341    return *this;
342}
343
344const std::string &ConstantExpression::description() const {
345    return mExpr;
346}
347
348bool ConstantExpression::descriptionIsTrivial() const {
349    return mTrivialDescription;
350}
351
352std::string ConstantExpression::value() const {
353    return rawValue(mValueKind);
354}
355
356std::string ConstantExpression::value(ScalarType::Kind castKind) const {
357    return rawValue(castKind);
358}
359
360std::string ConstantExpression::cppValue() const {
361    return cppValue(mValueKind);
362}
363
364std::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
386std::string ConstantExpression::javaValue() const {
387    return javaValue(mValueKind);
388}
389
390std::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
404std::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
411template<typename T>
412T 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
419size_t ConstantExpression::castSizeT() const {
420    return this->cast<size_t>();
421}
422
423/*
424
425Evaluating expressions in HIDL language
426
427The following rules are mostly like that in:
428http://en.cppreference.com/w/cpp/language/operator_arithmetic
429http://en.cppreference.com/w/cpp/language/operator_logical
430http://en.cppreference.com/w/cpp/language/operator_comparison
431http://en.cppreference.com/w/cpp/language/operator_other
432
433The type of literal is the first type which the value
434can fit from the list of types depending on the suffix and bases.
435
436suffix              decimal bases           hexadecimal bases
437no suffix           int32_t                 int32_t
438                    int64_t                 uint32_t
439                                            int64_t
440                                            uint64_t
441
442u/U                 uint32_t                (same as left)
443                    uint64_t
444
445l/L                 int64_t                 int64_t
446
447ul/UL/uL/Ul         uint64_t                uint64_t
448
449
450Note: There are no negative integer literals.
451      -1 is the unary minus applied to 1.
452
453Unary arithmetic and bitwise operators (~ + -):
454  don't change the type of the argument.
455  (so -1u = -(1u) has type uint32_t)
456
457Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
4581. Integral promotion is first applied on both sides.
4592. If both operands have the same type, no promotion is necessary.
4603. Usual arithmetic conversions.
461
462Integral promotion: if an operand is of a type with less than 32 bits,
463(including bool), it is promoted to int32_t.
464
465Usual arithmetic conversions:
4661. If operands are both signed or both unsigned, lesser conversion rank is
467   converted to greater conversion rank.
4682. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
4693. Otherwise, if signed's type can hold all values in unsigned's type,
470   -> signed's type
4714. Otherwise, both converted to the unsigned counterpart of the signed operand's
472   type.
473rank: bool < int8_t < int16_t < int32_t < int64_t
474
475
476Shift operators (<< >>):
4771. Integral promotion is applied on both sides.
4782. 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.
4813. 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")
4844. Shifting with negative number of bits is undefined. (Currently, the
485   parser will shift into the other direction. This behavior may change.)
4865. Shifting with number of bits exceeding the width of the type is undefined.
487   (Currently, 1 << 32 == 1. This behavior may change.)
488
489Logical operators (!, &&, ||):
4901. Convert first operand to bool. (true if non-zero, false otherwise)
4912. If short-circuited, return the result as type bool, value 1 or 0.
4923. Otherwise, convert second operand to bool, evaluate the result, and return
493   the result in the same fashion.
494
495Arithmetic comparison operators (< > <= >= == !=):
4961. Promote operands in the same way as binary arithmetic and bitwise operators.
497   (Integral promotion + Usual arithmetic conversions)
4982. Return type bool, value 0 or 1 the same way as logical operators.
499
500Ternary conditional operator (?:):
5011. Evaluate the conditional and evaluate the operands.
5022. 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