blob: 265f841a87ee9886f7fcb74b4f81dc0ae6c44fdb [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
42#define SWITCH_KIND(__cond__, __action__, __def__) \
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070043 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 } \
Yifan Hong52165692016-08-12 18:06:40 -070055
56namespace android {
57
Yifan Hongf24fa852016-09-23 11:03:15 -070058static inline bool isSupported(ScalarType::Kind kind) {
59 return SK(BOOL) == kind || ScalarType(kind).isValidEnumStorageType();
60}
61
Yifan Hong57886972016-08-17 10:42:15 -070062/* See docs at the end for details on integral promotion. */
63ScalarType::Kind integralPromotion(ScalarType::Kind in) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070064 return SK(INT32) < in ? in : SK(INT32); // note that KIND_INT32 < KIND_UINT32
Yifan Hong52165692016-08-12 18:06:40 -070065}
66
Yifan Hong57886972016-08-17 10:42:15 -070067/* See docs at the end for details on usual arithmetic conversion. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070068ScalarType::Kind usualArithmeticConversion(ScalarType::Kind lft,
69 ScalarType::Kind rgt) {
Yifan Hongf24fa852016-09-23 11:03:15 -070070 CHECK(isSupported(lft) && isSupported(rgt));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070071 // 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;
Yifan Hong57886972016-08-17 10:42:15 -070084
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070085 // 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 }
Yifan Hong52165692016-08-12 18:06:40 -070096}
Yifan Hong57886972016-08-17 10:42:15 -070097
98template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +000099T handleUnary(const std::string& op, T val) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700100 COMPUTE_UNARY(+)
101 COMPUTE_UNARY(-)
102 COMPUTE_UNARY(!)
103 COMPUTE_UNARY(~)
104 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700105 SHOULD_NOT_REACH() << "Could not handleUnary for " << op << " " << val;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700106 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700107}
108
109template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000110T handleBinaryCommon(T lval, const std::string& op, T rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700111 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.
Yifan Hongf24fa852016-09-23 11:03:15 -0700127 SHOULD_NOT_REACH() << "Could not handleBinaryCommon for "
128 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700129 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700130}
131
132template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000133T handleShift(T lval, const std::string& op, int64_t rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700134 // just cast rval to int64_t and it should fit.
135 COMPUTE_BINARY(>>)
136 COMPUTE_BINARY(<<)
137 // Should not reach here.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700138 SHOULD_NOT_REACH() << "Could not handleShift for "
Yifan Hongf24fa852016-09-23 11:03:15 -0700139 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700140 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700141}
142
Timur Iskhakov7296af12017-08-09 21:52:48 +0000143bool handleLogical(bool lval, const std::string& op, bool rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700144 COMPUTE_BINARY(||);
145 COMPUTE_BINARY(&&);
146 // Should not reach here.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700147 SHOULD_NOT_REACH() << "Could not handleLogical for "
Yifan Hongf24fa852016-09-23 11:03:15 -0700148 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700149 return false;
Yifan Hong57886972016-08-17 10:42:15 -0700150}
151
Timur Iskhakov7296af12017-08-09 21:52:48 +0000152std::unique_ptr<ConstantExpression> ConstantExpression::Zero(ScalarType::Kind kind) {
153 return ValueOf(kind, 0);
Yifan Hongf24fa852016-09-23 11:03:15 -0700154}
155
Timur Iskhakov7296af12017-08-09 21:52:48 +0000156std::unique_ptr<ConstantExpression> ConstantExpression::One(ScalarType::Kind kind) {
157 return ValueOf(kind, 1);
Yifan Hongf24fa852016-09-23 11:03:15 -0700158}
159
Timur Iskhakov7296af12017-08-09 21:52:48 +0000160std::unique_ptr<ConstantExpression> ConstantExpression::ValueOf(ScalarType::Kind kind,
161 uint64_t value) {
162 return std::make_unique<LiteralConstantExpression>(kind, value);
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700163}
164
Timur Iskhakov7296af12017-08-09 21:52:48 +0000165bool ConstantExpression::isEvaluated() const {
166 return mIsEvaluated;
167}
168
169LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value) {
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700170 CHECK(isSupported(kind));
Timur Iskhakov7296af12017-08-09 21:52:48 +0000171 mTrivialDescription = true;
172 mExpr = std::to_string(value);
173 mValueKind = kind;
174 mValue = value;
175 mIsEvaluated = true;
Yifan Hongf24fa852016-09-23 11:03:15 -0700176}
177
Timur Iskhakov7296af12017-08-09 21:52:48 +0000178LiteralConstantExpression::LiteralConstantExpression(const std::string& value) {
179 CHECK(!value.empty());
180 mIsEvaluated = true;
181 mTrivialDescription = true;
182 mExpr = value;
Yifan Hongf24fa852016-09-23 11:03:15 -0700183
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700184 bool isLong = false, isUnsigned = false;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000185 bool isHex = (value[0] == '0' && value.length() > 1 && (value[1] == 'x' || value[1] == 'X'));
186
187 auto rbegin = value.rbegin();
188 auto rend = value.rend();
189 for (; rbegin != rend && (*rbegin == 'u' || *rbegin == 'U' || *rbegin == 'l' || *rbegin == 'L');
190 ++rbegin) {
191 isUnsigned |= (*rbegin == 'u' || *rbegin == 'U');
192 isLong |= (*rbegin == 'l' || *rbegin == 'L');
Yifan Hong57886972016-08-17 10:42:15 -0700193 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000194 std::string newVal(value.begin(), rbegin.base());
195 CHECK(!newVal.empty());
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700196 bool parseOK = base::ParseUint(newVal, &mValue);
Yifan Hongf24fa852016-09-23 11:03:15 -0700197 CHECK(parseOK) << "Could not parse as integer: " << value;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700198
199 // guess literal type.
200 if(isLong) {
201 if(isUnsigned) // ul
202 mValueKind = SK(UINT64);
203 else // l
204 mValueKind = SK(INT64);
205 } else { // no l suffix
206 if(isUnsigned) { // u
207 if(mValue <= UINT32_MAX)
208 mValueKind = SK(UINT32);
209 else
210 mValueKind = SK(UINT64);
211 } else { // no suffix
212 if(isHex) {
213 if(mValue <= INT32_MAX) // mValue always >= 0
214 mValueKind = SK(INT32);
215 else if(mValue <= UINT32_MAX)
216 mValueKind = SK(UINT32);
217 else if(mValue <= INT64_MAX) // mValue always >= 0
218 mValueKind = SK(INT64);
219 else if(mValue <= UINT64_MAX)
220 mValueKind = SK(UINT64);
221 } else {
222 if(mValue <= INT32_MAX) // mValue always >= 0
223 mValueKind = SK(INT32);
224 else
225 mValueKind = SK(INT64);
226 }
227 }
228 }
Yifan Hong57886972016-08-17 10:42:15 -0700229}
230
Timur Iskhakov7296af12017-08-09 21:52:48 +0000231void LiteralConstantExpression::evaluate() {
232 // Evaluated in constructor
233 CHECK(isEvaluated());
234}
Yifan Hongf24fa852016-09-23 11:03:15 -0700235
Timur Iskhakov7296af12017-08-09 21:52:48 +0000236void UnaryConstantExpression::evaluate() {
237 if (isEvaluated()) return;
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700238 mUnary->evaluate();
Timur Iskhakov7296af12017-08-09 21:52:48 +0000239 mIsEvaluated = true;
240
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700241 mExpr = std::string("(") + mOp + mUnary->description() + ")";
242 mValueKind = mUnary->mValueKind;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000243
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700244#define CASE_UNARY(__type__) \
245 mValue = handleUnary(mOp, static_cast<__type__>(mUnary->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000246 return;
Yifan Hong57886972016-08-17 10:42:15 -0700247
Yifan Hongf24fa852016-09-23 11:03:15 -0700248 SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700249}
Yifan Hong57886972016-08-17 10:42:15 -0700250
Timur Iskhakov7296af12017-08-09 21:52:48 +0000251void BinaryConstantExpression::evaluate() {
252 if (isEvaluated()) return;
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700253 mLval->evaluate();
254 mRval->evaluate();
Timur Iskhakov7296af12017-08-09 21:52:48 +0000255 mIsEvaluated = true;
256
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700257 mExpr = std::string("(") + mLval->description() + " " + mOp + " " + mRval->description() + ")";
Yifan Hong57886972016-08-17 10:42:15 -0700258
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700259 bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
260
261 // CASE 1: + - * / % | ^ & < > <= >= == !=
262 if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
263 // promoted kind for both operands.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700264 ScalarType::Kind promoted = usualArithmeticConversion(integralPromotion(mLval->mValueKind),
265 integralPromotion(mRval->mValueKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700266 // result kind.
267 mValueKind = isArithmeticOrBitflip
268 ? promoted // arithmetic or bitflip operators generates promoted type
269 : SK(BOOL); // comparison operators generates bool
270
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700271#define CASE_BINARY_COMMON(__type__) \
272 mValue = handleBinaryCommon(static_cast<__type__>(mLval->mValue), mOp, \
273 static_cast<__type__>(mRval->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000274 return;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700275
Yifan Hongf24fa852016-09-23 11:03:15 -0700276 SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700277 }
278
279 // CASE 2: << >>
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700280 std::string newOp = mOp;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700281 if(OP_IS_BIN_SHIFT) {
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700282 mValueKind = integralPromotion(mLval->mValueKind);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700283 // instead of promoting rval, simply casting it to int64 should also be good.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700284 int64_t numBits = mRval->cast<int64_t>();
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700285 if(numBits < 0) {
286 // shifting with negative number of bits is undefined in C. In HIDL it
287 // is defined as shifting into the other direction.
Timur Iskhakov7296af12017-08-09 21:52:48 +0000288 newOp = OPEQ("<<") ? std::string(">>") : std::string("<<");
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700289 numBits = -numBits;
290 }
291
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700292#define CASE_SHIFT(__type__) \
293 mValue = handleShift(static_cast<__type__>(mLval->mValue), newOp, numBits); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000294 return;
Yifan Hong57886972016-08-17 10:42:15 -0700295
Yifan Hongf24fa852016-09-23 11:03:15 -0700296 SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700297 }
Yifan Hong57886972016-08-17 10:42:15 -0700298
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700299 // CASE 3: && ||
300 if(OP_IS_BIN_LOGICAL) {
301 mValueKind = SK(BOOL);
302 // easy; everything is bool.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700303 mValue = handleLogical(mLval->mValue, mOp, mRval->mValue);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700304 return;
305 }
Yifan Hong57886972016-08-17 10:42:15 -0700306
Yifan Hongf24fa852016-09-23 11:03:15 -0700307 SHOULD_NOT_REACH();
Yifan Hong57886972016-08-17 10:42:15 -0700308}
309
Timur Iskhakov7296af12017-08-09 21:52:48 +0000310void TernaryConstantExpression::evaluate() {
311 if (isEvaluated()) return;
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700312 mCond->evaluate();
313 mTrueVal->evaluate();
314 mFalseVal->evaluate();
Timur Iskhakov7296af12017-08-09 21:52:48 +0000315 mIsEvaluated = true;
316
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700317 mExpr = std::string("(") + mCond->description() + "?" + mTrueVal->description() + ":" +
318 mFalseVal->description() + ")";
Yifan Hongf24fa852016-09-23 11:03:15 -0700319
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700320 // note: for ?:, unlike arithmetic ops, integral promotion is not necessary.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700321 mValueKind = usualArithmeticConversion(mTrueVal->mValueKind, mFalseVal->mValueKind);
Yifan Hong57886972016-08-17 10:42:15 -0700322
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700323#define CASE_TERNARY(__type__) \
324 mValue = mCond->mValue ? (static_cast<__type__>(mTrueVal->mValue)) \
325 : (static_cast<__type__>(mFalseVal->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000326 return;
Yifan Hong57886972016-08-17 10:42:15 -0700327
Yifan Hongf24fa852016-09-23 11:03:15 -0700328 SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700329}
330
Timur Iskhakov7296af12017-08-09 21:52:48 +0000331void ReferenceConstantExpression::evaluate() {
332 if (isEvaluated()) return;
333
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700334 ConstantExpression* expr = mReference->constExpr();
Timur Iskhakov7296af12017-08-09 21:52:48 +0000335 CHECK(expr != nullptr);
336 expr->evaluate();
337
338 mValueKind = expr->mValueKind;
339 mValue = expr->mValue;
340 mIsEvaluated = true;
Yifan Hong52165692016-08-12 18:06:40 -0700341}
Yifan Hong57886972016-08-17 10:42:15 -0700342
Timur Iskhakov7296af12017-08-09 21:52:48 +0000343std::unique_ptr<ConstantExpression> ConstantExpression::addOne(ScalarType::Kind baseKind) {
344 auto ret = std::make_unique<BinaryConstantExpression>(
345 this, "+", ConstantExpression::One(baseKind).release());
346 ret->mTrivialDescription = true;
347 return ret;
Yifan Hongf24fa852016-09-23 11:03:15 -0700348}
349
Timur Iskhakov7296af12017-08-09 21:52:48 +0000350const std::string& ConstantExpression::description() const {
351 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700352 return mExpr;
Yifan Hong57886972016-08-17 10:42:15 -0700353}
354
Yifan Hong5706a432016-11-02 09:44:18 -0700355bool ConstantExpression::descriptionIsTrivial() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000356 CHECK(isEvaluated());
Yifan Hong5706a432016-11-02 09:44:18 -0700357 return mTrivialDescription;
358}
359
Yifan Hongfc610cd2016-09-22 13:34:45 -0700360std::string ConstantExpression::value() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000361 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700362 return rawValue(mValueKind);
363}
364
Yifan Hongc07b2022016-11-08 12:44:24 -0800365std::string ConstantExpression::value(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000366 CHECK(isEvaluated());
Yifan Hongc07b2022016-11-08 12:44:24 -0800367 return rawValue(castKind);
368}
369
Yifan Hongf24fa852016-09-23 11:03:15 -0700370std::string ConstantExpression::cppValue() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000371 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700372 return cppValue(mValueKind);
Yifan Hong52165692016-08-12 18:06:40 -0700373}
374
Yifan Hongfc610cd2016-09-22 13:34:45 -0700375std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000376 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700377 std::string literal(rawValue(castKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700378 // this is a hack to translate
379 // enum x : int64_t { y = 1l << 63 };
380 // into
381 // enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
382 // by adding the explicit cast.
383 // Because 9223372036854775808 is uint64_t, and
384 // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
385 // be narrowed to int64_t.
386 if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
Yifan Hong3b320f82016-11-01 15:15:54 -0700387 return strdup(("static_cast<"
388 + ScalarType(SK(INT64)).getCppStackType() // "int64_t"
389 + ">(" + literal + "ull)").c_str());
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700390 }
Yifan Hong57886972016-08-17 10:42:15 -0700391
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700392 // add suffix if necessary.
393 if(castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
394 if(castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
Yifan Hongfc610cd2016-09-22 13:34:45 -0700395 return literal;
Yifan Hong57886972016-08-17 10:42:15 -0700396}
397
Yifan Hongf24fa852016-09-23 11:03:15 -0700398std::string ConstantExpression::javaValue() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000399 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700400 return javaValue(mValueKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700401}
402
Yifan Hongf24fa852016-09-23 11:03:15 -0700403std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000404 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700405 switch(castKind) {
406 case SK(UINT64): return rawValue(SK(INT64)) + "L";
407 case SK(INT64): return rawValue(SK(INT64)) + "L";
408 case SK(UINT32): return rawValue(SK(INT32));
409 case SK(UINT16): return rawValue(SK(INT16));
410 case SK(UINT8) : return rawValue(SK(INT8));
411 case SK(BOOL) :
412 return this->cast<bool>() ? strdup("true") : strdup("false");
413 default: break;
414 }
415 return rawValue(castKind);
416}
417
418std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000419 CHECK(isEvaluated());
Yifan Hong57886972016-08-17 10:42:15 -0700420
Yifan Hongfc610cd2016-09-22 13:34:45 -0700421#define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
Yifan Hong57886972016-08-17 10:42:15 -0700422
Yifan Hongf24fa852016-09-23 11:03:15 -0700423 SWITCH_KIND(castKind, CASE_STR, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700424}
425
Yifan Hong19ca75a2016-08-31 10:20:03 -0700426template<typename T>
427T ConstantExpression::cast() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000428 CHECK(isEvaluated());
Yifan Hong57886972016-08-17 10:42:15 -0700429
Yifan Hong19ca75a2016-08-31 10:20:03 -0700430#define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
Yifan Hong57886972016-08-17 10:42:15 -0700431
Yifan Hongf24fa852016-09-23 11:03:15 -0700432 SWITCH_KIND(mValueKind, CASE_CAST_T, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700433}
434
Yifan Honge77ca132016-09-27 10:49:05 -0700435size_t ConstantExpression::castSizeT() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000436 CHECK(isEvaluated());
Yifan Honge77ca132016-09-27 10:49:05 -0700437 return this->cast<size_t>();
438}
439
Timur Iskhakov7296af12017-08-09 21:52:48 +0000440UnaryConstantExpression::UnaryConstantExpression(const std::string& op, ConstantExpression* value)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700441 : mUnary(value), mOp(op) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000442
443BinaryConstantExpression::BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
444 ConstantExpression* rval)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700445 : mLval(lval), mRval(rval), mOp(op) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000446
447TernaryConstantExpression::TernaryConstantExpression(ConstantExpression* cond,
448 ConstantExpression* trueVal,
449 ConstantExpression* falseVal)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700450 : mCond(cond), mTrueVal(trueVal), mFalseVal(falseVal) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000451
452ReferenceConstantExpression::ReferenceConstantExpression(const Reference<LocalIdentifier>& value,
453 const std::string& expr)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700454 : mReference(value) {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000455 mExpr = expr;
456}
457
Yifan Hong57886972016-08-17 10:42:15 -0700458/*
459
460Evaluating expressions in HIDL language
461
462The following rules are mostly like that in:
463http://en.cppreference.com/w/cpp/language/operator_arithmetic
464http://en.cppreference.com/w/cpp/language/operator_logical
465http://en.cppreference.com/w/cpp/language/operator_comparison
466http://en.cppreference.com/w/cpp/language/operator_other
467
468The type of literal is the first type which the value
469can fit from the list of types depending on the suffix and bases.
470
471suffix decimal bases hexadecimal bases
472no suffix int32_t int32_t
473 int64_t uint32_t
474 int64_t
475 uint64_t
476
477u/U uint32_t (same as left)
478 uint64_t
479
480l/L int64_t int64_t
481
482ul/UL/uL/Ul uint64_t uint64_t
483
484
485Note: There are no negative integer literals.
486 -1 is the unary minus applied to 1.
487
488Unary arithmetic and bitwise operators (~ + -):
489 don't change the type of the argument.
490 (so -1u = -(1u) has type uint32_t)
491
492Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
4931. Integral promotion is first applied on both sides.
4942. If both operands have the same type, no promotion is necessary.
4953. Usual arithmetic conversions.
496
497Integral promotion: if an operand is of a type with less than 32 bits,
498(including bool), it is promoted to int32_t.
499
500Usual arithmetic conversions:
5011. If operands are both signed or both unsigned, lesser conversion rank is
502 converted to greater conversion rank.
5032. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
5043. Otherwise, if signed's type can hold all values in unsigned's type,
505 -> signed's type
5064. Otherwise, both converted to the unsigned counterpart of the signed operand's
507 type.
508rank: bool < int8_t < int16_t < int32_t < int64_t
509
510
511Shift operators (<< >>):
5121. Integral promotion is applied on both sides.
5132. For unsigned a, a << b discards bits that shifts out.
514 For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
515 For signed negative a, a << b gives error.
5163. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
517 For signed negative a, a >> b discards bits that shifts out, and the signed
518 bit gets extended. ("arithmetic right shift")
5194. Shifting with negative number of bits is undefined. (Currently, the
520 parser will shift into the other direction. This behavior may change.)
5215. Shifting with number of bits exceeding the width of the type is undefined.
522 (Currently, 1 << 32 == 1. This behavior may change.)
523
524Logical operators (!, &&, ||):
5251. Convert first operand to bool. (true if non-zero, false otherwise)
5262. If short-circuited, return the result as type bool, value 1 or 0.
5273. Otherwise, convert second operand to bool, evaluate the result, and return
528 the result in the same fashion.
529
530Arithmetic comparison operators (< > <= >= == !=):
5311. Promote operands in the same way as binary arithmetic and bitwise operators.
532 (Integral promotion + Usual arithmetic conversions)
5332. Return type bool, value 0 or 1 the same way as logical operators.
534
535Ternary conditional operator (?:):
5361. Evaluate the conditional and evaluate the operands.
5372. Return type of expression is the type under usual arithmetic conversions on
538 the second and third operand. (No integral promotions necessary.)
539
540*/
541
Yifan Hong52165692016-08-12 18:06:40 -0700542} // namespace android
543