blob: d4df274867c5ff9b8d49ebc9178e3f20bed94fbe [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) {
Timur Iskhakov891a8662017-08-25 21:53:48 -070060 // TODO(b/64358435) move isSupported to EnumValue
Yifan Hongf24fa852016-09-23 11:03:15 -070061 return SK(BOOL) == kind || ScalarType(kind).isValidEnumStorageType();
62}
63
Yifan Hong57886972016-08-17 10:42:15 -070064/* See docs at the end for details on integral promotion. */
65ScalarType::Kind integralPromotion(ScalarType::Kind in) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070066 return SK(INT32) < in ? in : SK(INT32); // note that KIND_INT32 < KIND_UINT32
Yifan Hong52165692016-08-12 18:06:40 -070067}
68
Yifan Hong57886972016-08-17 10:42:15 -070069/* See docs at the end for details on usual arithmetic conversion. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070070ScalarType::Kind usualArithmeticConversion(ScalarType::Kind lft,
71 ScalarType::Kind rgt) {
Yifan Hongf24fa852016-09-23 11:03:15 -070072 CHECK(isSupported(lft) && isSupported(rgt));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070073 // Kinds in concern: bool, (u)int[8|16|32|64]
74 if(lft == rgt) return lft; // easy case
75 if(lft == SK(BOOL)) return rgt;
76 if(rgt == SK(BOOL)) return lft;
77 bool isLftSigned = (lft == SK(INT8)) || (lft == SK(INT16))
78 || (lft == SK(INT32)) || (lft == SK(INT64));
79 bool isRgtSigned = (rgt == SK(INT8)) || (rgt == SK(INT16))
80 || (rgt == SK(INT32)) || (rgt == SK(INT64));
81 if(isLftSigned == isRgtSigned) return lft < rgt ? rgt : lft;
82 ScalarType::Kind unsignedRank = isLftSigned ? rgt : lft;
83 ScalarType::Kind signedRank = isLftSigned ? lft : rgt;
84 if(unsignedRank >= signedRank) return unsignedRank;
85 if(signedRank > unsignedRank) return signedRank;
Yifan Hong57886972016-08-17 10:42:15 -070086
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070087 // Although there is such rule to return "the unsigned counterpart of
88 // the signed operand", it should not reach here in our HIDL grammar.
89 LOG(FATAL) << "Could not do usual arithmetic conversion for type "
90 << lft << "and" << rgt;
91 switch(signedRank) {
92 case SK(INT8): return SK(UINT8);
93 case SK(INT16): return SK(UINT16);
94 case SK(INT32): return SK(UINT32);
95 case SK(INT64): return SK(UINT64);
96 default: return SK(UINT64);
97 }
Yifan Hong52165692016-08-12 18:06:40 -070098}
Yifan Hong57886972016-08-17 10:42:15 -070099
100template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000101T handleUnary(const std::string& op, T val) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700102 COMPUTE_UNARY(+)
103 COMPUTE_UNARY(-)
104 COMPUTE_UNARY(!)
105 COMPUTE_UNARY(~)
106 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700107 SHOULD_NOT_REACH() << "Could not handleUnary for " << op << " " << val;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700108 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700109}
110
111template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000112T handleBinaryCommon(T lval, const std::string& op, T rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700113 COMPUTE_BINARY(+)
114 COMPUTE_BINARY(-)
115 COMPUTE_BINARY(*)
116 COMPUTE_BINARY(/)
117 COMPUTE_BINARY(%)
118 COMPUTE_BINARY(|)
119 COMPUTE_BINARY(^)
120 COMPUTE_BINARY(&)
121 // comparison operators: return 0 or 1 by nature.
122 COMPUTE_BINARY(==)
123 COMPUTE_BINARY(!=)
124 COMPUTE_BINARY(<)
125 COMPUTE_BINARY(>)
126 COMPUTE_BINARY(<=)
127 COMPUTE_BINARY(>=)
128 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700129 SHOULD_NOT_REACH() << "Could not handleBinaryCommon for "
130 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700131 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700132}
133
134template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000135T handleShift(T lval, const std::string& op, int64_t rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700136 // just cast rval to int64_t and it should fit.
137 COMPUTE_BINARY(>>)
138 COMPUTE_BINARY(<<)
139 // Should not reach here.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700140 SHOULD_NOT_REACH() << "Could not handleShift for "
Yifan Hongf24fa852016-09-23 11:03:15 -0700141 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700142 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700143}
144
Timur Iskhakov7296af12017-08-09 21:52:48 +0000145bool handleLogical(bool lval, const std::string& op, bool rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700146 COMPUTE_BINARY(||);
147 COMPUTE_BINARY(&&);
148 // Should not reach here.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700149 SHOULD_NOT_REACH() << "Could not handleLogical for "
Yifan Hongf24fa852016-09-23 11:03:15 -0700150 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700151 return false;
Yifan Hong57886972016-08-17 10:42:15 -0700152}
153
Timur Iskhakov7296af12017-08-09 21:52:48 +0000154std::unique_ptr<ConstantExpression> ConstantExpression::Zero(ScalarType::Kind kind) {
155 return ValueOf(kind, 0);
Yifan Hongf24fa852016-09-23 11:03:15 -0700156}
157
Timur Iskhakov7296af12017-08-09 21:52:48 +0000158std::unique_ptr<ConstantExpression> ConstantExpression::One(ScalarType::Kind kind) {
159 return ValueOf(kind, 1);
Yifan Hongf24fa852016-09-23 11:03:15 -0700160}
161
Timur Iskhakov7296af12017-08-09 21:52:48 +0000162std::unique_ptr<ConstantExpression> ConstantExpression::ValueOf(ScalarType::Kind kind,
163 uint64_t value) {
164 return std::make_unique<LiteralConstantExpression>(kind, value);
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700165}
166
Timur Iskhakov7296af12017-08-09 21:52:48 +0000167bool ConstantExpression::isEvaluated() const {
168 return mIsEvaluated;
169}
170
171LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value) {
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700172 CHECK(isSupported(kind));
Timur Iskhakov7296af12017-08-09 21:52:48 +0000173 mTrivialDescription = true;
174 mExpr = std::to_string(value);
175 mValueKind = kind;
176 mValue = value;
177 mIsEvaluated = true;
Yifan Hongf24fa852016-09-23 11:03:15 -0700178}
179
Timur Iskhakov7296af12017-08-09 21:52:48 +0000180LiteralConstantExpression::LiteralConstantExpression(const std::string& value) {
181 CHECK(!value.empty());
182 mIsEvaluated = true;
183 mTrivialDescription = true;
184 mExpr = value;
Yifan Hongf24fa852016-09-23 11:03:15 -0700185
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700186 bool isLong = false, isUnsigned = false;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000187 bool isHex = (value[0] == '0' && value.length() > 1 && (value[1] == 'x' || value[1] == 'X'));
188
189 auto rbegin = value.rbegin();
190 auto rend = value.rend();
191 for (; rbegin != rend && (*rbegin == 'u' || *rbegin == 'U' || *rbegin == 'l' || *rbegin == 'L');
192 ++rbegin) {
193 isUnsigned |= (*rbegin == 'u' || *rbegin == 'U');
194 isLong |= (*rbegin == 'l' || *rbegin == 'L');
Yifan Hong57886972016-08-17 10:42:15 -0700195 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000196 std::string newVal(value.begin(), rbegin.base());
197 CHECK(!newVal.empty());
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700198 bool parseOK = base::ParseUint(newVal, &mValue);
Yifan Hongf24fa852016-09-23 11:03:15 -0700199 CHECK(parseOK) << "Could not parse as integer: " << value;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700200
201 // guess literal type.
202 if(isLong) {
203 if(isUnsigned) // ul
204 mValueKind = SK(UINT64);
205 else // l
206 mValueKind = SK(INT64);
207 } else { // no l suffix
208 if(isUnsigned) { // u
209 if(mValue <= UINT32_MAX)
210 mValueKind = SK(UINT32);
211 else
212 mValueKind = SK(UINT64);
213 } else { // no suffix
214 if(isHex) {
215 if(mValue <= INT32_MAX) // mValue always >= 0
216 mValueKind = SK(INT32);
217 else if(mValue <= UINT32_MAX)
218 mValueKind = SK(UINT32);
219 else if(mValue <= INT64_MAX) // mValue always >= 0
220 mValueKind = SK(INT64);
221 else if(mValue <= UINT64_MAX)
222 mValueKind = SK(UINT64);
223 } else {
224 if(mValue <= INT32_MAX) // mValue always >= 0
225 mValueKind = SK(INT32);
226 else
227 mValueKind = SK(INT64);
228 }
229 }
230 }
Yifan Hong57886972016-08-17 10:42:15 -0700231}
232
Timur Iskhakov7296af12017-08-09 21:52:48 +0000233void LiteralConstantExpression::evaluate() {
234 // Evaluated in constructor
235 CHECK(isEvaluated());
236}
Yifan Hongf24fa852016-09-23 11:03:15 -0700237
Timur Iskhakov7296af12017-08-09 21:52:48 +0000238void UnaryConstantExpression::evaluate() {
239 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700240 CHECK(mUnary->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000241 mIsEvaluated = true;
242
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700243 mExpr = std::string("(") + mOp + mUnary->description() + ")";
244 mValueKind = mUnary->mValueKind;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000245
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700246#define CASE_UNARY(__type__) \
247 mValue = handleUnary(mOp, static_cast<__type__>(mUnary->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000248 return;
Yifan Hong57886972016-08-17 10:42:15 -0700249
Yifan Hongf24fa852016-09-23 11:03:15 -0700250 SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700251}
Yifan Hong57886972016-08-17 10:42:15 -0700252
Timur Iskhakov7296af12017-08-09 21:52:48 +0000253void BinaryConstantExpression::evaluate() {
254 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700255 CHECK(mLval->isEvaluated());
256 CHECK(mRval->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000257 mIsEvaluated = true;
258
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700259 mExpr = std::string("(") + mLval->description() + " " + mOp + " " + mRval->description() + ")";
Yifan Hong57886972016-08-17 10:42:15 -0700260
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700261 bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
262
263 // CASE 1: + - * / % | ^ & < > <= >= == !=
264 if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
265 // promoted kind for both operands.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700266 ScalarType::Kind promoted = usualArithmeticConversion(integralPromotion(mLval->mValueKind),
267 integralPromotion(mRval->mValueKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700268 // result kind.
269 mValueKind = isArithmeticOrBitflip
270 ? promoted // arithmetic or bitflip operators generates promoted type
271 : SK(BOOL); // comparison operators generates bool
272
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700273#define CASE_BINARY_COMMON(__type__) \
274 mValue = handleBinaryCommon(static_cast<__type__>(mLval->mValue), mOp, \
275 static_cast<__type__>(mRval->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000276 return;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700277
Yifan Hongf24fa852016-09-23 11:03:15 -0700278 SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700279 }
280
281 // CASE 2: << >>
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700282 std::string newOp = mOp;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700283 if(OP_IS_BIN_SHIFT) {
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700284 mValueKind = integralPromotion(mLval->mValueKind);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700285 // instead of promoting rval, simply casting it to int64 should also be good.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700286 int64_t numBits = mRval->cast<int64_t>();
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700287 if(numBits < 0) {
288 // shifting with negative number of bits is undefined in C. In HIDL it
289 // is defined as shifting into the other direction.
Timur Iskhakov7296af12017-08-09 21:52:48 +0000290 newOp = OPEQ("<<") ? std::string(">>") : std::string("<<");
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700291 numBits = -numBits;
292 }
293
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700294#define CASE_SHIFT(__type__) \
295 mValue = handleShift(static_cast<__type__>(mLval->mValue), newOp, numBits); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000296 return;
Yifan Hong57886972016-08-17 10:42:15 -0700297
Yifan Hongf24fa852016-09-23 11:03:15 -0700298 SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700299 }
Yifan Hong57886972016-08-17 10:42:15 -0700300
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700301 // CASE 3: && ||
302 if(OP_IS_BIN_LOGICAL) {
303 mValueKind = SK(BOOL);
304 // easy; everything is bool.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700305 mValue = handleLogical(mLval->mValue, mOp, mRval->mValue);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700306 return;
307 }
Yifan Hong57886972016-08-17 10:42:15 -0700308
Yifan Hongf24fa852016-09-23 11:03:15 -0700309 SHOULD_NOT_REACH();
Yifan Hong57886972016-08-17 10:42:15 -0700310}
311
Timur Iskhakov7296af12017-08-09 21:52:48 +0000312void TernaryConstantExpression::evaluate() {
313 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700314 CHECK(mCond->isEvaluated());
315 CHECK(mTrueVal->isEvaluated());
316 CHECK(mFalseVal->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000317 mIsEvaluated = true;
318
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700319 mExpr = std::string("(") + mCond->description() + "?" + mTrueVal->description() + ":" +
320 mFalseVal->description() + ")";
Yifan Hongf24fa852016-09-23 11:03:15 -0700321
Timur Iskhakov891a8662017-08-25 21:53:48 -0700322 // note: for ?:, unlike arithmetic ops, integral promotion is not processed.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700323 mValueKind = usualArithmeticConversion(mTrueVal->mValueKind, mFalseVal->mValueKind);
Yifan Hong57886972016-08-17 10:42:15 -0700324
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700325#define CASE_TERNARY(__type__) \
326 mValue = mCond->mValue ? (static_cast<__type__>(mTrueVal->mValue)) \
327 : (static_cast<__type__>(mFalseVal->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000328 return;
Yifan Hong57886972016-08-17 10:42:15 -0700329
Yifan Hongf24fa852016-09-23 11:03:15 -0700330 SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700331}
332
Timur Iskhakov7296af12017-08-09 21:52:48 +0000333void ReferenceConstantExpression::evaluate() {
334 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700335 CHECK(mReference->constExpr() != nullptr);
Timur Iskhakov7296af12017-08-09 21:52:48 +0000336
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700337 ConstantExpression* expr = mReference->constExpr();
Timur Iskhakov891a8662017-08-25 21:53:48 -0700338 CHECK(expr->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000339
340 mValueKind = expr->mValueKind;
341 mValue = expr->mValue;
342 mIsEvaluated = true;
Yifan Hong52165692016-08-12 18:06:40 -0700343}
Yifan Hong57886972016-08-17 10:42:15 -0700344
Timur Iskhakov7296af12017-08-09 21:52:48 +0000345std::unique_ptr<ConstantExpression> ConstantExpression::addOne(ScalarType::Kind baseKind) {
346 auto ret = std::make_unique<BinaryConstantExpression>(
347 this, "+", ConstantExpression::One(baseKind).release());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000348 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 Iskhakov891a8662017-08-25 21:53:48 -0700441status_t ConstantExpression::recursivePass(const std::function<status_t(ConstantExpression*)>& func,
442 std::unordered_set<const ConstantExpression*>* visited) {
443 if (visited->find(this) != visited->end()) return OK;
444 visited->insert(this);
445
446 for (auto* nextCE : getConstantExpressions()) {
447 status_t err = nextCE->recursivePass(func, visited);
448 if (err != OK) return err;
449 }
450
451 // Unlike types, constant expressions need to be proceeded after dependencies
452 status_t err = func(this);
453 if (err != OK) return err;
454
455 return OK;
456}
457
458std::vector<ConstantExpression*> LiteralConstantExpression::getConstantExpressions() const {
459 return {};
460}
461
Timur Iskhakov7296af12017-08-09 21:52:48 +0000462UnaryConstantExpression::UnaryConstantExpression(const std::string& op, ConstantExpression* value)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700463 : mUnary(value), mOp(op) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000464
Timur Iskhakov891a8662017-08-25 21:53:48 -0700465std::vector<ConstantExpression*> UnaryConstantExpression::getConstantExpressions() const {
466 return {mUnary};
467}
468
Timur Iskhakov7296af12017-08-09 21:52:48 +0000469BinaryConstantExpression::BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
470 ConstantExpression* rval)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700471 : mLval(lval), mRval(rval), mOp(op) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000472
Timur Iskhakov891a8662017-08-25 21:53:48 -0700473std::vector<ConstantExpression*> BinaryConstantExpression::getConstantExpressions() const {
474 return {mLval, mRval};
475}
476
Timur Iskhakov7296af12017-08-09 21:52:48 +0000477TernaryConstantExpression::TernaryConstantExpression(ConstantExpression* cond,
478 ConstantExpression* trueVal,
479 ConstantExpression* falseVal)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700480 : mCond(cond), mTrueVal(trueVal), mFalseVal(falseVal) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000481
Timur Iskhakov891a8662017-08-25 21:53:48 -0700482std::vector<ConstantExpression*> TernaryConstantExpression::getConstantExpressions() const {
483 return {mCond, mTrueVal, mFalseVal};
484}
485
Timur Iskhakov7296af12017-08-09 21:52:48 +0000486ReferenceConstantExpression::ReferenceConstantExpression(const Reference<LocalIdentifier>& value,
487 const std::string& expr)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700488 : mReference(value) {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000489 mExpr = expr;
Timur Iskhakov505e5612017-08-27 18:26:48 -0700490 mTrivialDescription = mExpr.empty();
Timur Iskhakov7296af12017-08-09 21:52:48 +0000491}
492
Timur Iskhakov891a8662017-08-25 21:53:48 -0700493std::vector<ConstantExpression*> ReferenceConstantExpression::getConstantExpressions() const {
494 CHECK(mReference->constExpr() != nullptr);
495 return {mReference->constExpr()};
496}
497
Yifan Hong57886972016-08-17 10:42:15 -0700498/*
499
500Evaluating expressions in HIDL language
501
502The following rules are mostly like that in:
503http://en.cppreference.com/w/cpp/language/operator_arithmetic
504http://en.cppreference.com/w/cpp/language/operator_logical
505http://en.cppreference.com/w/cpp/language/operator_comparison
506http://en.cppreference.com/w/cpp/language/operator_other
507
508The type of literal is the first type which the value
509can fit from the list of types depending on the suffix and bases.
510
511suffix decimal bases hexadecimal bases
512no suffix int32_t int32_t
513 int64_t uint32_t
514 int64_t
515 uint64_t
516
517u/U uint32_t (same as left)
518 uint64_t
519
520l/L int64_t int64_t
521
522ul/UL/uL/Ul uint64_t uint64_t
523
524
525Note: There are no negative integer literals.
526 -1 is the unary minus applied to 1.
527
528Unary arithmetic and bitwise operators (~ + -):
529 don't change the type of the argument.
530 (so -1u = -(1u) has type uint32_t)
531
532Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
5331. Integral promotion is first applied on both sides.
5342. If both operands have the same type, no promotion is necessary.
5353. Usual arithmetic conversions.
536
537Integral promotion: if an operand is of a type with less than 32 bits,
538(including bool), it is promoted to int32_t.
539
540Usual arithmetic conversions:
5411. If operands are both signed or both unsigned, lesser conversion rank is
542 converted to greater conversion rank.
5432. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
5443. Otherwise, if signed's type can hold all values in unsigned's type,
545 -> signed's type
5464. Otherwise, both converted to the unsigned counterpart of the signed operand's
547 type.
548rank: bool < int8_t < int16_t < int32_t < int64_t
549
550
551Shift operators (<< >>):
5521. Integral promotion is applied on both sides.
5532. For unsigned a, a << b discards bits that shifts out.
554 For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
555 For signed negative a, a << b gives error.
5563. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
557 For signed negative a, a >> b discards bits that shifts out, and the signed
558 bit gets extended. ("arithmetic right shift")
5594. Shifting with negative number of bits is undefined. (Currently, the
560 parser will shift into the other direction. This behavior may change.)
5615. Shifting with number of bits exceeding the width of the type is undefined.
562 (Currently, 1 << 32 == 1. This behavior may change.)
563
564Logical operators (!, &&, ||):
5651. Convert first operand to bool. (true if non-zero, false otherwise)
5662. If short-circuited, return the result as type bool, value 1 or 0.
5673. Otherwise, convert second operand to bool, evaluate the result, and return
568 the result in the same fashion.
569
570Arithmetic comparison operators (< > <= >= == !=):
5711. Promote operands in the same way as binary arithmetic and bitwise operators.
572 (Integral promotion + Usual arithmetic conversions)
5732. Return type bool, value 0 or 1 the same way as logical operators.
574
575Ternary conditional operator (?:):
5761. Evaluate the conditional and evaluate the operands.
5772. Return type of expression is the type under usual arithmetic conversions on
578 the second and third operand. (No integral promotions necessary.)
579
580*/
581
Yifan Hong52165692016-08-12 18:06:40 -0700582} // namespace android
583