blob: 94b645d29139d48669989a870f9d8e13cd266a25 [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
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
Yifan Hong52165692016-08-12 18:06:40 -070017#include "ConstantExpression.h"
18
Yifan Hong57886972016-08-17 10:42:15 -070019#include <stdio.h>
20#include <string>
Yifan Hong57886972016-08-17 10:42:15 -070021#include <android-base/parseint.h>
22#include <android-base/logging.h>
23#include <sstream>
24
Yifan Hongf24fa852016-09-23 11:03:15 -070025#include "EnumType.h"
Timur Iskhakov7296af12017-08-09 21:52:48 +000026#include "Scope.h" // LocalIdentifier
Yifan Hongf24fa852016-09-23 11:03:15 -070027
Yifan Hong57886972016-08-17 10:42:15 -070028// The macros are really nasty here. Consider removing
29// as many macros as possible.
30
Timur Iskhakovd27580c2017-08-09 20:14:52 -070031#define OPEQ(__y__) (std::string(mOp) == std::string(__y__))
32#define COMPUTE_UNARY(__op__) if (op == std::string(#__op__)) return __op__ val;
33#define COMPUTE_BINARY(__op__) if (op == std::string(#__op__)) return lval __op__ rval;
Yifan Hong57886972016-08-17 10:42:15 -070034#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__
Yifan Hongf24fa852016-09-23 11:03:15 -070040#define SHOULD_NOT_REACH() CHECK(false) << __LINE__ << ": should not reach here: "
Yifan Hong57886972016-08-17 10:42:15 -070041
Chih-Hung Hsieh306cc4b2017-08-02 14:59:25 -070042// NOLINT to suppress missing parentheses warnings about __def__.
Yifan Hong57886972016-08-17 10:42:15 -070043#define SWITCH_KIND(__cond__, __action__, __def__) \
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070044 switch(__cond__) { \
45 case SK(BOOL): __action__(bool) \
46 case SK(UINT8): __action__(uint8_t) \
47 case SK(INT8): __action__(int8_t) \
48 case SK(UINT16): __action__(uint16_t) \
49 case SK(INT16): __action__(int16_t) \
50 case SK(UINT32): __action__(uint32_t) \
51 case SK(INT32): __action__(int32_t) \
52 case SK(UINT64): __action__(uint64_t) \
53 case SK(INT64): __action__(int64_t) \
Chih-Hung Hsieh306cc4b2017-08-02 14:59:25 -070054 default: __def__ /* NOLINT */ \
55 }
Yifan Hong52165692016-08-12 18:06:40 -070056
57namespace android {
58
Yifan Hongf24fa852016-09-23 11:03:15 -070059static inline bool isSupported(ScalarType::Kind kind) {
60 return SK(BOOL) == kind || ScalarType(kind).isValidEnumStorageType();
61}
62
Yifan Hong57886972016-08-17 10:42:15 -070063/* See docs at the end for details on integral promotion. */
64ScalarType::Kind integralPromotion(ScalarType::Kind in) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070065 return SK(INT32) < in ? in : SK(INT32); // note that KIND_INT32 < KIND_UINT32
Yifan Hong52165692016-08-12 18:06:40 -070066}
67
Yifan Hong57886972016-08-17 10:42:15 -070068/* See docs at the end for details on usual arithmetic conversion. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070069ScalarType::Kind usualArithmeticConversion(ScalarType::Kind lft,
70 ScalarType::Kind rgt) {
Yifan Hongf24fa852016-09-23 11:03:15 -070071 CHECK(isSupported(lft) && isSupported(rgt));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070072 // Kinds in concern: bool, (u)int[8|16|32|64]
73 if(lft == rgt) return lft; // easy case
74 if(lft == SK(BOOL)) return rgt;
75 if(rgt == SK(BOOL)) return lft;
76 bool isLftSigned = (lft == SK(INT8)) || (lft == SK(INT16))
77 || (lft == SK(INT32)) || (lft == SK(INT64));
78 bool isRgtSigned = (rgt == SK(INT8)) || (rgt == SK(INT16))
79 || (rgt == SK(INT32)) || (rgt == SK(INT64));
80 if(isLftSigned == isRgtSigned) return lft < rgt ? rgt : lft;
81 ScalarType::Kind unsignedRank = isLftSigned ? rgt : lft;
82 ScalarType::Kind signedRank = isLftSigned ? lft : rgt;
83 if(unsignedRank >= signedRank) return unsignedRank;
84 if(signedRank > unsignedRank) return signedRank;
Yifan Hong57886972016-08-17 10:42:15 -070085
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070086 // Although there is such rule to return "the unsigned counterpart of
87 // the signed operand", it should not reach here in our HIDL grammar.
88 LOG(FATAL) << "Could not do usual arithmetic conversion for type "
89 << lft << "and" << rgt;
90 switch(signedRank) {
91 case SK(INT8): return SK(UINT8);
92 case SK(INT16): return SK(UINT16);
93 case SK(INT32): return SK(UINT32);
94 case SK(INT64): return SK(UINT64);
95 default: return SK(UINT64);
96 }
Yifan Hong52165692016-08-12 18:06:40 -070097}
Yifan Hong57886972016-08-17 10:42:15 -070098
99template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000100T handleUnary(const std::string& op, T val) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700101 COMPUTE_UNARY(+)
102 COMPUTE_UNARY(-)
103 COMPUTE_UNARY(!)
104 COMPUTE_UNARY(~)
105 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700106 SHOULD_NOT_REACH() << "Could not handleUnary for " << op << " " << val;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700107 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700108}
109
110template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000111T handleBinaryCommon(T lval, const std::string& op, T rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700112 COMPUTE_BINARY(+)
113 COMPUTE_BINARY(-)
114 COMPUTE_BINARY(*)
115 COMPUTE_BINARY(/)
116 COMPUTE_BINARY(%)
117 COMPUTE_BINARY(|)
118 COMPUTE_BINARY(^)
119 COMPUTE_BINARY(&)
120 // comparison operators: return 0 or 1 by nature.
121 COMPUTE_BINARY(==)
122 COMPUTE_BINARY(!=)
123 COMPUTE_BINARY(<)
124 COMPUTE_BINARY(>)
125 COMPUTE_BINARY(<=)
126 COMPUTE_BINARY(>=)
127 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700128 SHOULD_NOT_REACH() << "Could not handleBinaryCommon for "
129 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700130 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700131}
132
133template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000134T handleShift(T lval, const std::string& op, int64_t rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700135 // just cast rval to int64_t and it should fit.
136 COMPUTE_BINARY(>>)
137 COMPUTE_BINARY(<<)
138 // Should not reach here.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700139 SHOULD_NOT_REACH() << "Could not handleShift for "
Yifan Hongf24fa852016-09-23 11:03:15 -0700140 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700141 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700142}
143
Timur Iskhakov7296af12017-08-09 21:52:48 +0000144bool handleLogical(bool lval, const std::string& op, bool rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700145 COMPUTE_BINARY(||);
146 COMPUTE_BINARY(&&);
147 // Should not reach here.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700148 SHOULD_NOT_REACH() << "Could not handleLogical for "
Yifan Hongf24fa852016-09-23 11:03:15 -0700149 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700150 return false;
Yifan Hong57886972016-08-17 10:42:15 -0700151}
152
Timur Iskhakov7296af12017-08-09 21:52:48 +0000153std::unique_ptr<ConstantExpression> ConstantExpression::Zero(ScalarType::Kind kind) {
154 return ValueOf(kind, 0);
Yifan Hongf24fa852016-09-23 11:03:15 -0700155}
156
Timur Iskhakov7296af12017-08-09 21:52:48 +0000157std::unique_ptr<ConstantExpression> ConstantExpression::One(ScalarType::Kind kind) {
158 return ValueOf(kind, 1);
Yifan Hongf24fa852016-09-23 11:03:15 -0700159}
160
Timur Iskhakov7296af12017-08-09 21:52:48 +0000161std::unique_ptr<ConstantExpression> ConstantExpression::ValueOf(ScalarType::Kind kind,
162 uint64_t value) {
163 return std::make_unique<LiteralConstantExpression>(kind, value);
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700164}
165
Timur Iskhakov7296af12017-08-09 21:52:48 +0000166bool ConstantExpression::isEvaluated() const {
167 return mIsEvaluated;
168}
169
170LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value) {
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700171 CHECK(isSupported(kind));
Timur Iskhakov7296af12017-08-09 21:52:48 +0000172 mTrivialDescription = true;
173 mExpr = std::to_string(value);
174 mValueKind = kind;
175 mValue = value;
176 mIsEvaluated = true;
Yifan Hongf24fa852016-09-23 11:03:15 -0700177}
178
Timur Iskhakov7296af12017-08-09 21:52:48 +0000179LiteralConstantExpression::LiteralConstantExpression(const std::string& value) {
180 CHECK(!value.empty());
181 mIsEvaluated = true;
182 mTrivialDescription = true;
183 mExpr = value;
Yifan Hongf24fa852016-09-23 11:03:15 -0700184
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700185 bool isLong = false, isUnsigned = false;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000186 bool isHex = (value[0] == '0' && value.length() > 1 && (value[1] == 'x' || value[1] == 'X'));
187
188 auto rbegin = value.rbegin();
189 auto rend = value.rend();
190 for (; rbegin != rend && (*rbegin == 'u' || *rbegin == 'U' || *rbegin == 'l' || *rbegin == 'L');
191 ++rbegin) {
192 isUnsigned |= (*rbegin == 'u' || *rbegin == 'U');
193 isLong |= (*rbegin == 'l' || *rbegin == 'L');
Yifan Hong57886972016-08-17 10:42:15 -0700194 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000195 std::string newVal(value.begin(), rbegin.base());
196 CHECK(!newVal.empty());
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700197 bool parseOK = base::ParseUint(newVal, &mValue);
Yifan Hongf24fa852016-09-23 11:03:15 -0700198 CHECK(parseOK) << "Could not parse as integer: " << value;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700199
200 // guess literal type.
201 if(isLong) {
202 if(isUnsigned) // ul
203 mValueKind = SK(UINT64);
204 else // l
205 mValueKind = SK(INT64);
206 } else { // no l suffix
207 if(isUnsigned) { // u
208 if(mValue <= UINT32_MAX)
209 mValueKind = SK(UINT32);
210 else
211 mValueKind = SK(UINT64);
212 } else { // no suffix
213 if(isHex) {
214 if(mValue <= INT32_MAX) // mValue always >= 0
215 mValueKind = SK(INT32);
216 else if(mValue <= UINT32_MAX)
217 mValueKind = SK(UINT32);
218 else if(mValue <= INT64_MAX) // mValue always >= 0
219 mValueKind = SK(INT64);
220 else if(mValue <= UINT64_MAX)
221 mValueKind = SK(UINT64);
222 } else {
223 if(mValue <= INT32_MAX) // mValue always >= 0
224 mValueKind = SK(INT32);
225 else
226 mValueKind = SK(INT64);
227 }
228 }
229 }
Yifan Hong57886972016-08-17 10:42:15 -0700230}
231
Timur Iskhakov7296af12017-08-09 21:52:48 +0000232void LiteralConstantExpression::evaluate() {
233 // Evaluated in constructor
234 CHECK(isEvaluated());
235}
Yifan Hongf24fa852016-09-23 11:03:15 -0700236
Timur Iskhakov7296af12017-08-09 21:52:48 +0000237void UnaryConstantExpression::evaluate() {
238 if (isEvaluated()) return;
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700239 mUnary->evaluate();
Timur Iskhakov7296af12017-08-09 21:52:48 +0000240 mIsEvaluated = true;
241
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700242 mExpr = std::string("(") + mOp + mUnary->description() + ")";
243 mValueKind = mUnary->mValueKind;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000244
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700245#define CASE_UNARY(__type__) \
246 mValue = handleUnary(mOp, static_cast<__type__>(mUnary->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000247 return;
Yifan Hong57886972016-08-17 10:42:15 -0700248
Yifan Hongf24fa852016-09-23 11:03:15 -0700249 SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700250}
Yifan Hong57886972016-08-17 10:42:15 -0700251
Timur Iskhakov7296af12017-08-09 21:52:48 +0000252void BinaryConstantExpression::evaluate() {
253 if (isEvaluated()) return;
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700254 mLval->evaluate();
255 mRval->evaluate();
Timur Iskhakov7296af12017-08-09 21:52:48 +0000256 mIsEvaluated = true;
257
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700258 mExpr = std::string("(") + mLval->description() + " " + mOp + " " + mRval->description() + ")";
Yifan Hong57886972016-08-17 10:42:15 -0700259
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700260 bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
261
262 // CASE 1: + - * / % | ^ & < > <= >= == !=
263 if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
264 // promoted kind for both operands.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700265 ScalarType::Kind promoted = usualArithmeticConversion(integralPromotion(mLval->mValueKind),
266 integralPromotion(mRval->mValueKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700267 // result kind.
268 mValueKind = isArithmeticOrBitflip
269 ? promoted // arithmetic or bitflip operators generates promoted type
270 : SK(BOOL); // comparison operators generates bool
271
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700272#define CASE_BINARY_COMMON(__type__) \
273 mValue = handleBinaryCommon(static_cast<__type__>(mLval->mValue), mOp, \
274 static_cast<__type__>(mRval->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000275 return;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700276
Yifan Hongf24fa852016-09-23 11:03:15 -0700277 SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700278 }
279
280 // CASE 2: << >>
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700281 std::string newOp = mOp;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700282 if(OP_IS_BIN_SHIFT) {
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700283 mValueKind = integralPromotion(mLval->mValueKind);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700284 // instead of promoting rval, simply casting it to int64 should also be good.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700285 int64_t numBits = mRval->cast<int64_t>();
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700286 if(numBits < 0) {
287 // shifting with negative number of bits is undefined in C. In HIDL it
288 // is defined as shifting into the other direction.
Timur Iskhakov7296af12017-08-09 21:52:48 +0000289 newOp = OPEQ("<<") ? std::string(">>") : std::string("<<");
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700290 numBits = -numBits;
291 }
292
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700293#define CASE_SHIFT(__type__) \
294 mValue = handleShift(static_cast<__type__>(mLval->mValue), newOp, numBits); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000295 return;
Yifan Hong57886972016-08-17 10:42:15 -0700296
Yifan Hongf24fa852016-09-23 11:03:15 -0700297 SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700298 }
Yifan Hong57886972016-08-17 10:42:15 -0700299
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700300 // CASE 3: && ||
301 if(OP_IS_BIN_LOGICAL) {
302 mValueKind = SK(BOOL);
303 // easy; everything is bool.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700304 mValue = handleLogical(mLval->mValue, mOp, mRval->mValue);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700305 return;
306 }
Yifan Hong57886972016-08-17 10:42:15 -0700307
Yifan Hongf24fa852016-09-23 11:03:15 -0700308 SHOULD_NOT_REACH();
Yifan Hong57886972016-08-17 10:42:15 -0700309}
310
Timur Iskhakov7296af12017-08-09 21:52:48 +0000311void TernaryConstantExpression::evaluate() {
312 if (isEvaluated()) return;
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700313 mCond->evaluate();
314 mTrueVal->evaluate();
315 mFalseVal->evaluate();
Timur Iskhakov7296af12017-08-09 21:52:48 +0000316 mIsEvaluated = true;
317
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700318 mExpr = std::string("(") + mCond->description() + "?" + mTrueVal->description() + ":" +
319 mFalseVal->description() + ")";
Yifan Hongf24fa852016-09-23 11:03:15 -0700320
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700321 // note: for ?:, unlike arithmetic ops, integral promotion is not necessary.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700322 mValueKind = usualArithmeticConversion(mTrueVal->mValueKind, mFalseVal->mValueKind);
Yifan Hong57886972016-08-17 10:42:15 -0700323
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700324#define CASE_TERNARY(__type__) \
325 mValue = mCond->mValue ? (static_cast<__type__>(mTrueVal->mValue)) \
326 : (static_cast<__type__>(mFalseVal->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000327 return;
Yifan Hong57886972016-08-17 10:42:15 -0700328
Yifan Hongf24fa852016-09-23 11:03:15 -0700329 SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700330}
331
Timur Iskhakov7296af12017-08-09 21:52:48 +0000332void ReferenceConstantExpression::evaluate() {
333 if (isEvaluated()) return;
334
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700335 ConstantExpression* expr = mReference->constExpr();
Timur Iskhakov7296af12017-08-09 21:52:48 +0000336 CHECK(expr != nullptr);
337 expr->evaluate();
338
339 mValueKind = expr->mValueKind;
340 mValue = expr->mValue;
341 mIsEvaluated = true;
Yifan Hong52165692016-08-12 18:06:40 -0700342}
Yifan Hong57886972016-08-17 10:42:15 -0700343
Timur Iskhakov7296af12017-08-09 21:52:48 +0000344std::unique_ptr<ConstantExpression> ConstantExpression::addOne(ScalarType::Kind baseKind) {
345 auto ret = std::make_unique<BinaryConstantExpression>(
346 this, "+", ConstantExpression::One(baseKind).release());
347 ret->mTrivialDescription = true;
348 return ret;
Yifan Hongf24fa852016-09-23 11:03:15 -0700349}
350
Timur Iskhakov7296af12017-08-09 21:52:48 +0000351const std::string& ConstantExpression::description() const {
352 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700353 return mExpr;
Yifan Hong57886972016-08-17 10:42:15 -0700354}
355
Yifan Hong5706a432016-11-02 09:44:18 -0700356bool ConstantExpression::descriptionIsTrivial() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000357 CHECK(isEvaluated());
Yifan Hong5706a432016-11-02 09:44:18 -0700358 return mTrivialDescription;
359}
360
Yifan Hongfc610cd2016-09-22 13:34:45 -0700361std::string ConstantExpression::value() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000362 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700363 return rawValue(mValueKind);
364}
365
Yifan Hongc07b2022016-11-08 12:44:24 -0800366std::string ConstantExpression::value(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000367 CHECK(isEvaluated());
Yifan Hongc07b2022016-11-08 12:44:24 -0800368 return rawValue(castKind);
369}
370
Yifan Hongf24fa852016-09-23 11:03:15 -0700371std::string ConstantExpression::cppValue() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000372 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700373 return cppValue(mValueKind);
Yifan Hong52165692016-08-12 18:06:40 -0700374}
375
Yifan Hongfc610cd2016-09-22 13:34:45 -0700376std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000377 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700378 std::string literal(rawValue(castKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700379 // this is a hack to translate
380 // enum x : int64_t { y = 1l << 63 };
381 // into
382 // enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
383 // by adding the explicit cast.
384 // Because 9223372036854775808 is uint64_t, and
385 // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
386 // be narrowed to int64_t.
387 if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
Yifan Hong3b320f82016-11-01 15:15:54 -0700388 return strdup(("static_cast<"
389 + ScalarType(SK(INT64)).getCppStackType() // "int64_t"
390 + ">(" + literal + "ull)").c_str());
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700391 }
Yifan Hong57886972016-08-17 10:42:15 -0700392
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700393 // add suffix if necessary.
394 if(castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
395 if(castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
Yifan Hongfc610cd2016-09-22 13:34:45 -0700396 return literal;
Yifan Hong57886972016-08-17 10:42:15 -0700397}
398
Yifan Hongf24fa852016-09-23 11:03:15 -0700399std::string ConstantExpression::javaValue() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000400 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700401 return javaValue(mValueKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700402}
403
Yifan Hongf24fa852016-09-23 11:03:15 -0700404std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000405 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700406 switch(castKind) {
407 case SK(UINT64): return rawValue(SK(INT64)) + "L";
408 case SK(INT64): return rawValue(SK(INT64)) + "L";
409 case SK(UINT32): return rawValue(SK(INT32));
410 case SK(UINT16): return rawValue(SK(INT16));
411 case SK(UINT8) : return rawValue(SK(INT8));
412 case SK(BOOL) :
413 return this->cast<bool>() ? strdup("true") : strdup("false");
414 default: break;
415 }
416 return rawValue(castKind);
417}
418
419std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000420 CHECK(isEvaluated());
Yifan Hong57886972016-08-17 10:42:15 -0700421
Yifan Hongfc610cd2016-09-22 13:34:45 -0700422#define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
Yifan Hong57886972016-08-17 10:42:15 -0700423
Yifan Hongf24fa852016-09-23 11:03:15 -0700424 SWITCH_KIND(castKind, CASE_STR, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700425}
426
Yifan Hong19ca75a2016-08-31 10:20:03 -0700427template<typename T>
428T ConstantExpression::cast() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000429 CHECK(isEvaluated());
Yifan Hong57886972016-08-17 10:42:15 -0700430
Yifan Hong19ca75a2016-08-31 10:20:03 -0700431#define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
Yifan Hong57886972016-08-17 10:42:15 -0700432
Yifan Hongf24fa852016-09-23 11:03:15 -0700433 SWITCH_KIND(mValueKind, CASE_CAST_T, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700434}
435
Yifan Honge77ca132016-09-27 10:49:05 -0700436size_t ConstantExpression::castSizeT() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000437 CHECK(isEvaluated());
Yifan Honge77ca132016-09-27 10:49:05 -0700438 return this->cast<size_t>();
439}
440
Timur Iskhakov7296af12017-08-09 21:52:48 +0000441UnaryConstantExpression::UnaryConstantExpression(const std::string& op, ConstantExpression* value)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700442 : mUnary(value), mOp(op) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000443
444BinaryConstantExpression::BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
445 ConstantExpression* rval)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700446 : mLval(lval), mRval(rval), mOp(op) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000447
448TernaryConstantExpression::TernaryConstantExpression(ConstantExpression* cond,
449 ConstantExpression* trueVal,
450 ConstantExpression* falseVal)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700451 : mCond(cond), mTrueVal(trueVal), mFalseVal(falseVal) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000452
453ReferenceConstantExpression::ReferenceConstantExpression(const Reference<LocalIdentifier>& value,
454 const std::string& expr)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700455 : mReference(value) {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000456 mExpr = expr;
457}
458
Yifan Hong57886972016-08-17 10:42:15 -0700459/*
460
461Evaluating expressions in HIDL language
462
463The following rules are mostly like that in:
464http://en.cppreference.com/w/cpp/language/operator_arithmetic
465http://en.cppreference.com/w/cpp/language/operator_logical
466http://en.cppreference.com/w/cpp/language/operator_comparison
467http://en.cppreference.com/w/cpp/language/operator_other
468
469The type of literal is the first type which the value
470can fit from the list of types depending on the suffix and bases.
471
472suffix decimal bases hexadecimal bases
473no suffix int32_t int32_t
474 int64_t uint32_t
475 int64_t
476 uint64_t
477
478u/U uint32_t (same as left)
479 uint64_t
480
481l/L int64_t int64_t
482
483ul/UL/uL/Ul uint64_t uint64_t
484
485
486Note: There are no negative integer literals.
487 -1 is the unary minus applied to 1.
488
489Unary arithmetic and bitwise operators (~ + -):
490 don't change the type of the argument.
491 (so -1u = -(1u) has type uint32_t)
492
493Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
4941. Integral promotion is first applied on both sides.
4952. If both operands have the same type, no promotion is necessary.
4963. Usual arithmetic conversions.
497
498Integral promotion: if an operand is of a type with less than 32 bits,
499(including bool), it is promoted to int32_t.
500
501Usual arithmetic conversions:
5021. If operands are both signed or both unsigned, lesser conversion rank is
503 converted to greater conversion rank.
5042. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
5053. Otherwise, if signed's type can hold all values in unsigned's type,
506 -> signed's type
5074. Otherwise, both converted to the unsigned counterpart of the signed operand's
508 type.
509rank: bool < int8_t < int16_t < int32_t < int64_t
510
511
512Shift operators (<< >>):
5131. Integral promotion is applied on both sides.
5142. For unsigned a, a << b discards bits that shifts out.
515 For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
516 For signed negative a, a << b gives error.
5173. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
518 For signed negative a, a >> b discards bits that shifts out, and the signed
519 bit gets extended. ("arithmetic right shift")
5204. Shifting with negative number of bits is undefined. (Currently, the
521 parser will shift into the other direction. This behavior may change.)
5225. Shifting with number of bits exceeding the width of the type is undefined.
523 (Currently, 1 << 32 == 1. This behavior may change.)
524
525Logical operators (!, &&, ||):
5261. Convert first operand to bool. (true if non-zero, false otherwise)
5272. If short-circuited, return the result as type bool, value 1 or 0.
5283. Otherwise, convert second operand to bool, evaluate the result, and return
529 the result in the same fashion.
530
531Arithmetic comparison operators (< > <= >= == !=):
5321. Promote operands in the same way as binary arithmetic and bitwise operators.
533 (Integral promotion + Usual arithmetic conversions)
5342. Return type bool, value 0 or 1 the same way as logical operators.
535
536Ternary conditional operator (?:):
5371. Evaluate the conditional and evaluate the operands.
5382. Return type of expression is the type under usual arithmetic conversions on
539 the second and third operand. (No integral promotions necessary.)
540
541*/
542
Yifan Hong52165692016-08-12 18:06:40 -0700543} // namespace android
544