blob: a593025a71e5ece5aef493c6c098370f8e82f6da [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 <android-base/logging.h>
Timur Iskhakovb58f4182017-08-29 15:19:24 -070020#include <android-base/parseint.h>
21#include <stdio.h>
22#include <algorithm>
Yifan Hong57886972016-08-17 10:42:15 -070023#include <sstream>
Timur Iskhakovb58f4182017-08-29 15:19:24 -070024#include <string>
Yifan Hong57886972016-08-17 10:42:15 -070025
Yifan Hongf24fa852016-09-23 11:03:15 -070026#include "EnumType.h"
Timur Iskhakov7296af12017-08-09 21:52:48 +000027#include "Scope.h" // LocalIdentifier
Yifan Hongf24fa852016-09-23 11:03:15 -070028
Yifan Hong57886972016-08-17 10:42:15 -070029// The macros are really nasty here. Consider removing
30// as many macros as possible.
31
Timur Iskhakovd27580c2017-08-09 20:14:52 -070032#define OPEQ(__y__) (std::string(mOp) == std::string(__y__))
33#define COMPUTE_UNARY(__op__) if (op == std::string(#__op__)) return __op__ val;
34#define COMPUTE_BINARY(__op__) if (op == std::string(#__op__)) return lval __op__ rval;
Yifan Hong57886972016-08-17 10:42:15 -070035#define OP_IS_BIN_ARITHMETIC (OPEQ("+") || OPEQ("-") || OPEQ("*") || OPEQ("/") || OPEQ("%"))
36#define OP_IS_BIN_BITFLIP (OPEQ("|") || OPEQ("^") || OPEQ("&"))
37#define OP_IS_BIN_COMP (OPEQ("<") || OPEQ(">") || OPEQ("<=") || OPEQ(">=") || OPEQ("==") || OPEQ("!="))
38#define OP_IS_BIN_SHIFT (OPEQ(">>") || OPEQ("<<"))
39#define OP_IS_BIN_LOGICAL (OPEQ("||") || OPEQ("&&"))
40#define SK(__x__) ScalarType::Kind::KIND_##__x__
Yifan Hongf24fa852016-09-23 11:03:15 -070041#define SHOULD_NOT_REACH() CHECK(false) << __LINE__ << ": should not reach here: "
Yifan Hong57886972016-08-17 10:42:15 -070042
Chih-Hung Hsieh306cc4b2017-08-02 14:59:25 -070043// NOLINT to suppress missing parentheses warnings about __def__.
Yifan Hong57886972016-08-17 10:42:15 -070044#define SWITCH_KIND(__cond__, __action__, __def__) \
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070045 switch(__cond__) { \
46 case SK(BOOL): __action__(bool) \
47 case SK(UINT8): __action__(uint8_t) \
48 case SK(INT8): __action__(int8_t) \
49 case SK(UINT16): __action__(uint16_t) \
50 case SK(INT16): __action__(int16_t) \
51 case SK(UINT32): __action__(uint32_t) \
52 case SK(INT32): __action__(int32_t) \
53 case SK(UINT64): __action__(uint64_t) \
54 case SK(INT64): __action__(int64_t) \
Chih-Hung Hsieh306cc4b2017-08-02 14:59:25 -070055 default: __def__ /* NOLINT */ \
56 }
Yifan Hong52165692016-08-12 18:06:40 -070057
58namespace android {
59
Yifan Hongf24fa852016-09-23 11:03:15 -070060static inline bool isSupported(ScalarType::Kind kind) {
Timur Iskhakov891a8662017-08-25 21:53:48 -070061 // TODO(b/64358435) move isSupported to EnumValue
Timur Iskhakov63f39902017-08-29 15:47:29 -070062 return SK(BOOL) == kind || ScalarType(kind, nullptr /* parent */).isValidEnumStorageType();
Yifan Hongf24fa852016-09-23 11:03:15 -070063}
64
Yifan Hong57886972016-08-17 10:42:15 -070065/* See docs at the end for details on integral promotion. */
66ScalarType::Kind integralPromotion(ScalarType::Kind in) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070067 return SK(INT32) < in ? in : SK(INT32); // note that KIND_INT32 < KIND_UINT32
Yifan Hong52165692016-08-12 18:06:40 -070068}
69
Yifan Hong57886972016-08-17 10:42:15 -070070/* See docs at the end for details on usual arithmetic conversion. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070071ScalarType::Kind usualArithmeticConversion(ScalarType::Kind lft,
72 ScalarType::Kind rgt) {
Yifan Hongf24fa852016-09-23 11:03:15 -070073 CHECK(isSupported(lft) && isSupported(rgt));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070074 // Kinds in concern: bool, (u)int[8|16|32|64]
75 if(lft == rgt) return lft; // easy case
76 if(lft == SK(BOOL)) return rgt;
77 if(rgt == SK(BOOL)) return lft;
78 bool isLftSigned = (lft == SK(INT8)) || (lft == SK(INT16))
79 || (lft == SK(INT32)) || (lft == SK(INT64));
80 bool isRgtSigned = (rgt == SK(INT8)) || (rgt == SK(INT16))
81 || (rgt == SK(INT32)) || (rgt == SK(INT64));
82 if(isLftSigned == isRgtSigned) return lft < rgt ? rgt : lft;
83 ScalarType::Kind unsignedRank = isLftSigned ? rgt : lft;
84 ScalarType::Kind signedRank = isLftSigned ? lft : rgt;
85 if(unsignedRank >= signedRank) return unsignedRank;
86 if(signedRank > unsignedRank) return signedRank;
Yifan Hong57886972016-08-17 10:42:15 -070087
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070088 // Although there is such rule to return "the unsigned counterpart of
89 // the signed operand", it should not reach here in our HIDL grammar.
90 LOG(FATAL) << "Could not do usual arithmetic conversion for type "
91 << lft << "and" << rgt;
92 switch(signedRank) {
93 case SK(INT8): return SK(UINT8);
94 case SK(INT16): return SK(UINT16);
95 case SK(INT32): return SK(UINT32);
96 case SK(INT64): return SK(UINT64);
97 default: return SK(UINT64);
98 }
Yifan Hong52165692016-08-12 18:06:40 -070099}
Yifan Hong57886972016-08-17 10:42:15 -0700100
101template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000102T handleUnary(const std::string& op, T val) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700103 COMPUTE_UNARY(+)
104 COMPUTE_UNARY(-)
105 COMPUTE_UNARY(!)
106 COMPUTE_UNARY(~)
107 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700108 SHOULD_NOT_REACH() << "Could not handleUnary for " << op << " " << val;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700109 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700110}
111
112template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000113T handleBinaryCommon(T lval, const std::string& op, T rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700114 COMPUTE_BINARY(+)
115 COMPUTE_BINARY(-)
116 COMPUTE_BINARY(*)
117 COMPUTE_BINARY(/)
118 COMPUTE_BINARY(%)
119 COMPUTE_BINARY(|)
120 COMPUTE_BINARY(^)
121 COMPUTE_BINARY(&)
122 // comparison operators: return 0 or 1 by nature.
123 COMPUTE_BINARY(==)
124 COMPUTE_BINARY(!=)
125 COMPUTE_BINARY(<)
126 COMPUTE_BINARY(>)
127 COMPUTE_BINARY(<=)
128 COMPUTE_BINARY(>=)
129 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700130 SHOULD_NOT_REACH() << "Could not handleBinaryCommon for "
131 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700132 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700133}
134
135template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000136T handleShift(T lval, const std::string& op, int64_t rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700137 // just cast rval to int64_t and it should fit.
138 COMPUTE_BINARY(>>)
139 COMPUTE_BINARY(<<)
140 // Should not reach here.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700141 SHOULD_NOT_REACH() << "Could not handleShift for "
Yifan Hongf24fa852016-09-23 11:03:15 -0700142 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700143 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700144}
145
Timur Iskhakov7296af12017-08-09 21:52:48 +0000146bool handleLogical(bool lval, const std::string& op, bool rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700147 COMPUTE_BINARY(||);
148 COMPUTE_BINARY(&&);
149 // Should not reach here.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700150 SHOULD_NOT_REACH() << "Could not handleLogical for "
Yifan Hongf24fa852016-09-23 11:03:15 -0700151 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700152 return false;
Yifan Hong57886972016-08-17 10:42:15 -0700153}
154
Timur Iskhakov7296af12017-08-09 21:52:48 +0000155std::unique_ptr<ConstantExpression> ConstantExpression::Zero(ScalarType::Kind kind) {
156 return ValueOf(kind, 0);
Yifan Hongf24fa852016-09-23 11:03:15 -0700157}
158
Timur Iskhakov7296af12017-08-09 21:52:48 +0000159std::unique_ptr<ConstantExpression> ConstantExpression::One(ScalarType::Kind kind) {
160 return ValueOf(kind, 1);
Yifan Hongf24fa852016-09-23 11:03:15 -0700161}
162
Timur Iskhakov7296af12017-08-09 21:52:48 +0000163std::unique_ptr<ConstantExpression> ConstantExpression::ValueOf(ScalarType::Kind kind,
164 uint64_t value) {
165 return std::make_unique<LiteralConstantExpression>(kind, value);
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700166}
167
Timur Iskhakov7296af12017-08-09 21:52:48 +0000168bool ConstantExpression::isEvaluated() const {
169 return mIsEvaluated;
170}
171
172LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value) {
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700173 CHECK(isSupported(kind));
Timur Iskhakov7296af12017-08-09 21:52:48 +0000174 mTrivialDescription = true;
175 mExpr = std::to_string(value);
176 mValueKind = kind;
177 mValue = value;
178 mIsEvaluated = true;
Yifan Hongf24fa852016-09-23 11:03:15 -0700179}
180
Timur Iskhakov7296af12017-08-09 21:52:48 +0000181LiteralConstantExpression::LiteralConstantExpression(const std::string& value) {
182 CHECK(!value.empty());
183 mIsEvaluated = true;
184 mTrivialDescription = true;
185 mExpr = value;
Yifan Hongf24fa852016-09-23 11:03:15 -0700186
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700187 bool isLong = false, isUnsigned = false;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000188 bool isHex = (value[0] == '0' && value.length() > 1 && (value[1] == 'x' || value[1] == 'X'));
189
190 auto rbegin = value.rbegin();
191 auto rend = value.rend();
192 for (; rbegin != rend && (*rbegin == 'u' || *rbegin == 'U' || *rbegin == 'l' || *rbegin == 'L');
193 ++rbegin) {
194 isUnsigned |= (*rbegin == 'u' || *rbegin == 'U');
195 isLong |= (*rbegin == 'l' || *rbegin == 'L');
Yifan Hong57886972016-08-17 10:42:15 -0700196 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000197 std::string newVal(value.begin(), rbegin.base());
198 CHECK(!newVal.empty());
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700199 bool parseOK = base::ParseUint(newVal, &mValue);
Yifan Hongf24fa852016-09-23 11:03:15 -0700200 CHECK(parseOK) << "Could not parse as integer: " << value;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700201
202 // guess literal type.
203 if(isLong) {
204 if(isUnsigned) // ul
205 mValueKind = SK(UINT64);
206 else // l
207 mValueKind = SK(INT64);
208 } else { // no l suffix
209 if(isUnsigned) { // u
210 if(mValue <= UINT32_MAX)
211 mValueKind = SK(UINT32);
212 else
213 mValueKind = SK(UINT64);
214 } else { // no suffix
215 if(isHex) {
216 if(mValue <= INT32_MAX) // mValue always >= 0
217 mValueKind = SK(INT32);
218 else if(mValue <= UINT32_MAX)
219 mValueKind = SK(UINT32);
220 else if(mValue <= INT64_MAX) // mValue always >= 0
221 mValueKind = SK(INT64);
222 else if(mValue <= UINT64_MAX)
223 mValueKind = SK(UINT64);
224 } else {
225 if(mValue <= INT32_MAX) // mValue always >= 0
226 mValueKind = SK(INT32);
227 else
228 mValueKind = SK(INT64);
229 }
230 }
231 }
Yifan Hong57886972016-08-17 10:42:15 -0700232}
233
Timur Iskhakov7296af12017-08-09 21:52:48 +0000234void LiteralConstantExpression::evaluate() {
235 // Evaluated in constructor
236 CHECK(isEvaluated());
237}
Yifan Hongf24fa852016-09-23 11:03:15 -0700238
Timur Iskhakov7296af12017-08-09 21:52:48 +0000239void UnaryConstantExpression::evaluate() {
240 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700241 CHECK(mUnary->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000242 mIsEvaluated = true;
243
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700244 mExpr = std::string("(") + mOp + mUnary->description() + ")";
245 mValueKind = mUnary->mValueKind;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000246
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700247#define CASE_UNARY(__type__) \
248 mValue = handleUnary(mOp, static_cast<__type__>(mUnary->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000249 return;
Yifan Hong57886972016-08-17 10:42:15 -0700250
Yifan Hongf24fa852016-09-23 11:03:15 -0700251 SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700252}
Yifan Hong57886972016-08-17 10:42:15 -0700253
Timur Iskhakov7296af12017-08-09 21:52:48 +0000254void BinaryConstantExpression::evaluate() {
255 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700256 CHECK(mLval->isEvaluated());
257 CHECK(mRval->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000258 mIsEvaluated = true;
259
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700260 mExpr = std::string("(") + mLval->description() + " " + mOp + " " + mRval->description() + ")";
Yifan Hong57886972016-08-17 10:42:15 -0700261
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700262 bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
263
264 // CASE 1: + - * / % | ^ & < > <= >= == !=
265 if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
266 // promoted kind for both operands.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700267 ScalarType::Kind promoted = usualArithmeticConversion(integralPromotion(mLval->mValueKind),
268 integralPromotion(mRval->mValueKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700269 // result kind.
270 mValueKind = isArithmeticOrBitflip
271 ? promoted // arithmetic or bitflip operators generates promoted type
272 : SK(BOOL); // comparison operators generates bool
273
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700274#define CASE_BINARY_COMMON(__type__) \
275 mValue = handleBinaryCommon(static_cast<__type__>(mLval->mValue), mOp, \
276 static_cast<__type__>(mRval->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000277 return;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700278
Yifan Hongf24fa852016-09-23 11:03:15 -0700279 SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700280 }
281
282 // CASE 2: << >>
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700283 std::string newOp = mOp;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700284 if(OP_IS_BIN_SHIFT) {
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700285 mValueKind = integralPromotion(mLval->mValueKind);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700286 // instead of promoting rval, simply casting it to int64 should also be good.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700287 int64_t numBits = mRval->cast<int64_t>();
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700288 if(numBits < 0) {
289 // shifting with negative number of bits is undefined in C. In HIDL it
290 // is defined as shifting into the other direction.
Timur Iskhakov7296af12017-08-09 21:52:48 +0000291 newOp = OPEQ("<<") ? std::string(">>") : std::string("<<");
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700292 numBits = -numBits;
293 }
294
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700295#define CASE_SHIFT(__type__) \
296 mValue = handleShift(static_cast<__type__>(mLval->mValue), newOp, numBits); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000297 return;
Yifan Hong57886972016-08-17 10:42:15 -0700298
Yifan Hongf24fa852016-09-23 11:03:15 -0700299 SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700300 }
Yifan Hong57886972016-08-17 10:42:15 -0700301
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700302 // CASE 3: && ||
303 if(OP_IS_BIN_LOGICAL) {
304 mValueKind = SK(BOOL);
305 // easy; everything is bool.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700306 mValue = handleLogical(mLval->mValue, mOp, mRval->mValue);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700307 return;
308 }
Yifan Hong57886972016-08-17 10:42:15 -0700309
Yifan Hongf24fa852016-09-23 11:03:15 -0700310 SHOULD_NOT_REACH();
Yifan Hong57886972016-08-17 10:42:15 -0700311}
312
Timur Iskhakov7296af12017-08-09 21:52:48 +0000313void TernaryConstantExpression::evaluate() {
314 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700315 CHECK(mCond->isEvaluated());
316 CHECK(mTrueVal->isEvaluated());
317 CHECK(mFalseVal->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000318 mIsEvaluated = true;
319
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700320 mExpr = std::string("(") + mCond->description() + "?" + mTrueVal->description() + ":" +
321 mFalseVal->description() + ")";
Yifan Hongf24fa852016-09-23 11:03:15 -0700322
Timur Iskhakov891a8662017-08-25 21:53:48 -0700323 // note: for ?:, unlike arithmetic ops, integral promotion is not processed.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700324 mValueKind = usualArithmeticConversion(mTrueVal->mValueKind, mFalseVal->mValueKind);
Yifan Hong57886972016-08-17 10:42:15 -0700325
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700326#define CASE_TERNARY(__type__) \
327 mValue = mCond->mValue ? (static_cast<__type__>(mTrueVal->mValue)) \
328 : (static_cast<__type__>(mFalseVal->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000329 return;
Yifan Hong57886972016-08-17 10:42:15 -0700330
Yifan Hongf24fa852016-09-23 11:03:15 -0700331 SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700332}
333
Timur Iskhakov7296af12017-08-09 21:52:48 +0000334void ReferenceConstantExpression::evaluate() {
335 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700336 CHECK(mReference->constExpr() != nullptr);
Timur Iskhakov7296af12017-08-09 21:52:48 +0000337
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700338 ConstantExpression* expr = mReference->constExpr();
Timur Iskhakov891a8662017-08-25 21:53:48 -0700339 CHECK(expr->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000340
341 mValueKind = expr->mValueKind;
342 mValue = expr->mValue;
343 mIsEvaluated = true;
Yifan Hong52165692016-08-12 18:06:40 -0700344}
Yifan Hong57886972016-08-17 10:42:15 -0700345
Timur Iskhakov7296af12017-08-09 21:52:48 +0000346std::unique_ptr<ConstantExpression> ConstantExpression::addOne(ScalarType::Kind baseKind) {
347 auto ret = std::make_unique<BinaryConstantExpression>(
348 this, "+", ConstantExpression::One(baseKind).release());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000349 return ret;
Yifan Hongf24fa852016-09-23 11:03:15 -0700350}
351
Timur Iskhakov7296af12017-08-09 21:52:48 +0000352const std::string& ConstantExpression::description() const {
353 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700354 return mExpr;
Yifan Hong57886972016-08-17 10:42:15 -0700355}
356
Yifan Hong5706a432016-11-02 09:44:18 -0700357bool ConstantExpression::descriptionIsTrivial() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000358 CHECK(isEvaluated());
Yifan Hong5706a432016-11-02 09:44:18 -0700359 return mTrivialDescription;
360}
361
Yifan Hongfc610cd2016-09-22 13:34:45 -0700362std::string ConstantExpression::value() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000363 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700364 return rawValue(mValueKind);
365}
366
Yifan Hongc07b2022016-11-08 12:44:24 -0800367std::string ConstantExpression::value(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000368 CHECK(isEvaluated());
Yifan Hongc07b2022016-11-08 12:44:24 -0800369 return rawValue(castKind);
370}
371
Yifan Hongf24fa852016-09-23 11:03:15 -0700372std::string ConstantExpression::cppValue() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000373 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700374 return cppValue(mValueKind);
Yifan Hong52165692016-08-12 18:06:40 -0700375}
376
Yifan Hongfc610cd2016-09-22 13:34:45 -0700377std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000378 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700379 std::string literal(rawValue(castKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700380 // this is a hack to translate
381 // enum x : int64_t { y = 1l << 63 };
382 // into
383 // enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
384 // by adding the explicit cast.
385 // Because 9223372036854775808 is uint64_t, and
386 // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
387 // be narrowed to int64_t.
388 if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
Timur Iskhakov63f39902017-08-29 15:47:29 -0700389 return strdup(("static_cast<" +
390 ScalarType(SK(INT64), nullptr /* parent */).getCppStackType() // "int64_t"
391 + ">(" + literal + "ull)")
392 .c_str());
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700393 }
Yifan Hong57886972016-08-17 10:42:15 -0700394
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700395 // add suffix if necessary.
396 if(castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
397 if(castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
Yifan Hongfc610cd2016-09-22 13:34:45 -0700398 return literal;
Yifan Hong57886972016-08-17 10:42:15 -0700399}
400
Yifan Hongf24fa852016-09-23 11:03:15 -0700401std::string ConstantExpression::javaValue() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000402 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700403 return javaValue(mValueKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700404}
405
Yifan Hongf24fa852016-09-23 11:03:15 -0700406std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000407 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700408 switch(castKind) {
409 case SK(UINT64): return rawValue(SK(INT64)) + "L";
410 case SK(INT64): return rawValue(SK(INT64)) + "L";
411 case SK(UINT32): return rawValue(SK(INT32));
412 case SK(UINT16): return rawValue(SK(INT16));
413 case SK(UINT8) : return rawValue(SK(INT8));
414 case SK(BOOL) :
415 return this->cast<bool>() ? strdup("true") : strdup("false");
416 default: break;
417 }
418 return rawValue(castKind);
419}
420
421std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000422 CHECK(isEvaluated());
Yifan Hong57886972016-08-17 10:42:15 -0700423
Yifan Hongfc610cd2016-09-22 13:34:45 -0700424#define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
Yifan Hong57886972016-08-17 10:42:15 -0700425
Yifan Hongf24fa852016-09-23 11:03:15 -0700426 SWITCH_KIND(castKind, CASE_STR, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700427}
428
Yifan Hong19ca75a2016-08-31 10:20:03 -0700429template<typename T>
430T ConstantExpression::cast() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000431 CHECK(isEvaluated());
Yifan Hong57886972016-08-17 10:42:15 -0700432
Yifan Hong19ca75a2016-08-31 10:20:03 -0700433#define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
Yifan Hong57886972016-08-17 10:42:15 -0700434
Yifan Hongf24fa852016-09-23 11:03:15 -0700435 SWITCH_KIND(mValueKind, CASE_CAST_T, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700436}
437
Yifan Honge77ca132016-09-27 10:49:05 -0700438size_t ConstantExpression::castSizeT() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000439 CHECK(isEvaluated());
Yifan Honge77ca132016-09-27 10:49:05 -0700440 return this->cast<size_t>();
441}
442
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700443std::vector<ConstantExpression*> ConstantExpression::getConstantExpressions() {
444 const auto& constRet = static_cast<const ConstantExpression*>(this)->getConstantExpressions();
445 std::vector<ConstantExpression*> ret(constRet.size());
446 std::transform(constRet.begin(), constRet.end(), ret.begin(),
447 [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
448 return ret;
449}
450
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700451std::vector<Reference<LocalIdentifier>*> ConstantExpression::getReferences() {
452 const auto& constRet = static_cast<const ConstantExpression*>(this)->getReferences();
453 std::vector<Reference<LocalIdentifier>*> ret(constRet.size());
454 std::transform(constRet.begin(), constRet.end(), ret.begin(),
455 [](const auto* ce) { return const_cast<Reference<LocalIdentifier>*>(ce); });
456 return ret;
457}
458
459std::vector<const Reference<LocalIdentifier>*> ConstantExpression::getReferences() const {
460 return {};
461}
462
Timur Iskhakov891a8662017-08-25 21:53:48 -0700463status_t ConstantExpression::recursivePass(const std::function<status_t(ConstantExpression*)>& func,
464 std::unordered_set<const ConstantExpression*>* visited) {
Timur Iskhakov35930c42017-08-28 18:49:54 -0700465 if (mIsPostParseCompleted) return OK;
466
Timur Iskhakov891a8662017-08-25 21:53:48 -0700467 if (visited->find(this) != visited->end()) return OK;
468 visited->insert(this);
469
470 for (auto* nextCE : getConstantExpressions()) {
471 status_t err = nextCE->recursivePass(func, visited);
472 if (err != OK) return err;
473 }
474
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700475 for (auto* nextRef : getReferences()) {
476 auto* nextCE = nextRef->shallowGet()->constExpr();
477 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
478 status_t err = nextCE->recursivePass(func, visited);
479 if (err != OK) return err;
480 }
481
Timur Iskhakov891a8662017-08-25 21:53:48 -0700482 // Unlike types, constant expressions need to be proceeded after dependencies
483 status_t err = func(this);
484 if (err != OK) return err;
485
486 return OK;
487}
488
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700489status_t ConstantExpression::recursivePass(
490 const std::function<status_t(const ConstantExpression*)>& func,
491 std::unordered_set<const ConstantExpression*>* visited) const {
492
493 if (mIsPostParseCompleted) return OK;
494
495 if (visited->find(this) != visited->end()) return OK;
496 visited->insert(this);
497
498 for (const auto* nextCE : getConstantExpressions()) {
499 status_t err = nextCE->recursivePass(func, visited);
500 if (err != OK) return err;
501 }
502
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700503 for (const auto* nextRef : getReferences()) {
504 const auto* nextCE = nextRef->shallowGet()->constExpr();
505 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
506 status_t err = nextCE->recursivePass(func, visited);
507 if (err != OK) return err;
508 }
509
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700510 // Unlike types, constant expressions need to be proceeded after dependencies
511 status_t err = func(this);
512 if (err != OK) return err;
513
514 return OK;
515}
516
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700517ConstantExpression::CheckAcyclicStatus::CheckAcyclicStatus(status_t status,
518 const ConstantExpression* cycleEnd)
519 : status(status), cycleEnd(cycleEnd) {
520 CHECK(cycleEnd == nullptr || status != OK);
521}
522
523ConstantExpression::CheckAcyclicStatus ConstantExpression::checkAcyclic(
524 std::unordered_set<const ConstantExpression*>* visited,
525 std::unordered_set<const ConstantExpression*>* stack) const {
526 if (stack->find(this) != stack->end()) {
527 std::cerr << "ERROR: Cyclic declaration:\n";
528 return CheckAcyclicStatus(UNKNOWN_ERROR, this);
529 }
530
531 if (visited->find(this) != visited->end()) return CheckAcyclicStatus(OK);
532 visited->insert(this);
533 stack->insert(this);
534
535 for (const auto* nextCE : getConstantExpressions()) {
536 auto err = nextCE->checkAcyclic(visited, stack);
537 if (err.status != OK) {
538 return err;
539 }
540 }
541
542 for (const auto* nextRef : getReferences()) {
543 const auto* nextCE = nextRef->shallowGet()->constExpr();
544 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
545 auto err = nextCE->checkAcyclic(visited, stack);
546
547 if (err.status != OK) {
548 if (err.cycleEnd == nullptr) return err;
549
550 // Only ReferenceConstantExpression has references,
551 // mExpr is defined explicitly before evaluation
552
553 std::cerr << " ";
554 if (!mTrivialDescription) {
555 std::cerr << " '" << mExpr << "' ";
556 };
557 std::cerr << "at " << nextRef->location() << "\n";
558
559 if (err.cycleEnd == this) {
560 return CheckAcyclicStatus(err.status);
561 }
562 return err;
563 }
564 }
565
566 CHECK(stack->find(this) != stack->end());
567 stack->erase(this);
568 return CheckAcyclicStatus(OK);
569}
570
Timur Iskhakov35930c42017-08-28 18:49:54 -0700571void ConstantExpression::setPostParseCompleted() {
572 CHECK(!mIsPostParseCompleted);
573 mIsPostParseCompleted = true;
574}
575
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700576std::vector<const ConstantExpression*> LiteralConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700577 return {};
578}
579
Timur Iskhakov7296af12017-08-09 21:52:48 +0000580UnaryConstantExpression::UnaryConstantExpression(const std::string& op, ConstantExpression* value)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700581 : mUnary(value), mOp(op) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000582
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700583std::vector<const ConstantExpression*> UnaryConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700584 return {mUnary};
585}
586
Timur Iskhakov7296af12017-08-09 21:52:48 +0000587BinaryConstantExpression::BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
588 ConstantExpression* rval)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700589 : mLval(lval), mRval(rval), mOp(op) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000590
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700591std::vector<const ConstantExpression*> BinaryConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700592 return {mLval, mRval};
593}
594
Timur Iskhakov7296af12017-08-09 21:52:48 +0000595TernaryConstantExpression::TernaryConstantExpression(ConstantExpression* cond,
596 ConstantExpression* trueVal,
597 ConstantExpression* falseVal)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700598 : mCond(cond), mTrueVal(trueVal), mFalseVal(falseVal) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000599
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700600std::vector<const ConstantExpression*> TernaryConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700601 return {mCond, mTrueVal, mFalseVal};
602}
603
Timur Iskhakov7296af12017-08-09 21:52:48 +0000604ReferenceConstantExpression::ReferenceConstantExpression(const Reference<LocalIdentifier>& value,
605 const std::string& expr)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700606 : mReference(value) {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000607 mExpr = expr;
Timur Iskhakov505e5612017-08-27 18:26:48 -0700608 mTrivialDescription = mExpr.empty();
Timur Iskhakov7296af12017-08-09 21:52:48 +0000609}
610
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700611std::vector<const ConstantExpression*> ReferenceConstantExpression::getConstantExpressions() const {
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700612 // Returns reference instead
613 return {};
614}
615
616std::vector<const Reference<LocalIdentifier>*> ReferenceConstantExpression::getReferences() const {
617 return {&mReference};
Timur Iskhakov891a8662017-08-25 21:53:48 -0700618}
619
Yifan Hong57886972016-08-17 10:42:15 -0700620/*
621
622Evaluating expressions in HIDL language
623
624The following rules are mostly like that in:
625http://en.cppreference.com/w/cpp/language/operator_arithmetic
626http://en.cppreference.com/w/cpp/language/operator_logical
627http://en.cppreference.com/w/cpp/language/operator_comparison
628http://en.cppreference.com/w/cpp/language/operator_other
629
630The type of literal is the first type which the value
631can fit from the list of types depending on the suffix and bases.
632
633suffix decimal bases hexadecimal bases
634no suffix int32_t int32_t
635 int64_t uint32_t
636 int64_t
637 uint64_t
638
639u/U uint32_t (same as left)
640 uint64_t
641
642l/L int64_t int64_t
643
644ul/UL/uL/Ul uint64_t uint64_t
645
646
647Note: There are no negative integer literals.
648 -1 is the unary minus applied to 1.
649
650Unary arithmetic and bitwise operators (~ + -):
651 don't change the type of the argument.
652 (so -1u = -(1u) has type uint32_t)
653
654Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
6551. Integral promotion is first applied on both sides.
6562. If both operands have the same type, no promotion is necessary.
6573. Usual arithmetic conversions.
658
659Integral promotion: if an operand is of a type with less than 32 bits,
660(including bool), it is promoted to int32_t.
661
662Usual arithmetic conversions:
6631. If operands are both signed or both unsigned, lesser conversion rank is
664 converted to greater conversion rank.
6652. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
6663. Otherwise, if signed's type can hold all values in unsigned's type,
667 -> signed's type
6684. Otherwise, both converted to the unsigned counterpart of the signed operand's
669 type.
670rank: bool < int8_t < int16_t < int32_t < int64_t
671
672
673Shift operators (<< >>):
6741. Integral promotion is applied on both sides.
6752. For unsigned a, a << b discards bits that shifts out.
676 For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
677 For signed negative a, a << b gives error.
6783. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
679 For signed negative a, a >> b discards bits that shifts out, and the signed
680 bit gets extended. ("arithmetic right shift")
6814. Shifting with negative number of bits is undefined. (Currently, the
682 parser will shift into the other direction. This behavior may change.)
6835. Shifting with number of bits exceeding the width of the type is undefined.
684 (Currently, 1 << 32 == 1. This behavior may change.)
685
686Logical operators (!, &&, ||):
6871. Convert first operand to bool. (true if non-zero, false otherwise)
6882. If short-circuited, return the result as type bool, value 1 or 0.
6893. Otherwise, convert second operand to bool, evaluate the result, and return
690 the result in the same fashion.
691
692Arithmetic comparison operators (< > <= >= == !=):
6931. Promote operands in the same way as binary arithmetic and bitwise operators.
694 (Integral promotion + Usual arithmetic conversions)
6952. Return type bool, value 0 or 1 the same way as logical operators.
696
697Ternary conditional operator (?:):
6981. Evaluate the conditional and evaluate the operands.
6992. Return type of expression is the type under usual arithmetic conversions on
700 the second and third operand. (No integral promotions necessary.)
701
702*/
703
Yifan Hong52165692016-08-12 18:06:40 -0700704} // namespace android
705