blob: 5f022c8ef72f9af86751dfe9ea4fa89a733cb2e9 [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>
Timur Iskhakove8ee6a02017-09-06 11:42:10 -070023#include <iostream>
Yifan Hong57886972016-08-17 10:42:15 -070024#include <sstream>
Timur Iskhakovb58f4182017-08-29 15:19:24 -070025#include <string>
Yifan Hong57886972016-08-17 10:42:15 -070026
Yifan Hongf24fa852016-09-23 11:03:15 -070027#include "EnumType.h"
Timur Iskhakov7296af12017-08-09 21:52:48 +000028#include "Scope.h" // LocalIdentifier
Yifan Hongf24fa852016-09-23 11:03:15 -070029
Yifan Hong57886972016-08-17 10:42:15 -070030// The macros are really nasty here. Consider removing
31// as many macros as possible.
32
Timur Iskhakovd27580c2017-08-09 20:14:52 -070033#define OPEQ(__y__) (std::string(mOp) == std::string(__y__))
34#define COMPUTE_UNARY(__op__) if (op == std::string(#__op__)) return __op__ val;
35#define COMPUTE_BINARY(__op__) if (op == std::string(#__op__)) return lval __op__ rval;
Yifan Hong57886972016-08-17 10:42:15 -070036#define OP_IS_BIN_ARITHMETIC (OPEQ("+") || OPEQ("-") || OPEQ("*") || OPEQ("/") || OPEQ("%"))
37#define OP_IS_BIN_BITFLIP (OPEQ("|") || OPEQ("^") || OPEQ("&"))
38#define OP_IS_BIN_COMP (OPEQ("<") || OPEQ(">") || OPEQ("<=") || OPEQ(">=") || OPEQ("==") || OPEQ("!="))
39#define OP_IS_BIN_SHIFT (OPEQ(">>") || OPEQ("<<"))
40#define OP_IS_BIN_LOGICAL (OPEQ("||") || OPEQ("&&"))
41#define SK(__x__) ScalarType::Kind::KIND_##__x__
Yifan Hongf24fa852016-09-23 11:03:15 -070042#define SHOULD_NOT_REACH() CHECK(false) << __LINE__ << ": should not reach here: "
Yifan Hong57886972016-08-17 10:42:15 -070043
Chih-Hung Hsieh306cc4b2017-08-02 14:59:25 -070044// NOLINT to suppress missing parentheses warnings about __def__.
Yifan Hong57886972016-08-17 10:42:15 -070045#define SWITCH_KIND(__cond__, __action__, __def__) \
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070046 switch(__cond__) { \
47 case SK(BOOL): __action__(bool) \
48 case SK(UINT8): __action__(uint8_t) \
49 case SK(INT8): __action__(int8_t) \
50 case SK(UINT16): __action__(uint16_t) \
51 case SK(INT16): __action__(int16_t) \
52 case SK(UINT32): __action__(uint32_t) \
53 case SK(INT32): __action__(int32_t) \
54 case SK(UINT64): __action__(uint64_t) \
55 case SK(INT64): __action__(int64_t) \
Chih-Hung Hsieh306cc4b2017-08-02 14:59:25 -070056 default: __def__ /* NOLINT */ \
57 }
Yifan Hong52165692016-08-12 18:06:40 -070058
59namespace android {
60
Yifan Hongf24fa852016-09-23 11:03:15 -070061static inline bool isSupported(ScalarType::Kind kind) {
Timur Iskhakov891a8662017-08-25 21:53:48 -070062 // TODO(b/64358435) move isSupported to EnumValue
Timur Iskhakov63f39902017-08-29 15:47:29 -070063 return SK(BOOL) == kind || ScalarType(kind, nullptr /* parent */).isValidEnumStorageType();
Yifan Hongf24fa852016-09-23 11:03:15 -070064}
65
Yifan Hong57886972016-08-17 10:42:15 -070066/* See docs at the end for details on integral promotion. */
67ScalarType::Kind integralPromotion(ScalarType::Kind in) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070068 return SK(INT32) < in ? in : SK(INT32); // note that KIND_INT32 < KIND_UINT32
Yifan Hong52165692016-08-12 18:06:40 -070069}
70
Yifan Hong57886972016-08-17 10:42:15 -070071/* See docs at the end for details on usual arithmetic conversion. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070072ScalarType::Kind usualArithmeticConversion(ScalarType::Kind lft,
73 ScalarType::Kind rgt) {
Yifan Hongf24fa852016-09-23 11:03:15 -070074 CHECK(isSupported(lft) && isSupported(rgt));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070075 // Kinds in concern: bool, (u)int[8|16|32|64]
76 if(lft == rgt) return lft; // easy case
77 if(lft == SK(BOOL)) return rgt;
78 if(rgt == SK(BOOL)) return lft;
79 bool isLftSigned = (lft == SK(INT8)) || (lft == SK(INT16))
80 || (lft == SK(INT32)) || (lft == SK(INT64));
81 bool isRgtSigned = (rgt == SK(INT8)) || (rgt == SK(INT16))
82 || (rgt == SK(INT32)) || (rgt == SK(INT64));
83 if(isLftSigned == isRgtSigned) return lft < rgt ? rgt : lft;
84 ScalarType::Kind unsignedRank = isLftSigned ? rgt : lft;
85 ScalarType::Kind signedRank = isLftSigned ? lft : rgt;
86 if(unsignedRank >= signedRank) return unsignedRank;
87 if(signedRank > unsignedRank) return signedRank;
Yifan Hong57886972016-08-17 10:42:15 -070088
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070089 // Although there is such rule to return "the unsigned counterpart of
90 // the signed operand", it should not reach here in our HIDL grammar.
91 LOG(FATAL) << "Could not do usual arithmetic conversion for type "
92 << lft << "and" << rgt;
93 switch(signedRank) {
94 case SK(INT8): return SK(UINT8);
95 case SK(INT16): return SK(UINT16);
96 case SK(INT32): return SK(UINT32);
97 case SK(INT64): return SK(UINT64);
98 default: return SK(UINT64);
99 }
Yifan Hong52165692016-08-12 18:06:40 -0700100}
Yifan Hong57886972016-08-17 10:42:15 -0700101
102template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000103T handleUnary(const std::string& op, T val) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700104 COMPUTE_UNARY(+)
105 COMPUTE_UNARY(-)
106 COMPUTE_UNARY(!)
107 COMPUTE_UNARY(~)
108 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700109 SHOULD_NOT_REACH() << "Could not handleUnary for " << op << " " << val;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700110 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700111}
112
113template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000114T handleBinaryCommon(T lval, const std::string& op, T rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700115 COMPUTE_BINARY(+)
116 COMPUTE_BINARY(-)
117 COMPUTE_BINARY(*)
118 COMPUTE_BINARY(/)
119 COMPUTE_BINARY(%)
120 COMPUTE_BINARY(|)
121 COMPUTE_BINARY(^)
122 COMPUTE_BINARY(&)
123 // comparison operators: return 0 or 1 by nature.
124 COMPUTE_BINARY(==)
125 COMPUTE_BINARY(!=)
126 COMPUTE_BINARY(<)
127 COMPUTE_BINARY(>)
128 COMPUTE_BINARY(<=)
129 COMPUTE_BINARY(>=)
130 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700131 SHOULD_NOT_REACH() << "Could not handleBinaryCommon for "
132 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700133 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700134}
135
136template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000137T handleShift(T lval, const std::string& op, int64_t rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700138 // just cast rval to int64_t and it should fit.
139 COMPUTE_BINARY(>>)
140 COMPUTE_BINARY(<<)
141 // Should not reach here.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700142 SHOULD_NOT_REACH() << "Could not handleShift for "
Yifan Hongf24fa852016-09-23 11:03:15 -0700143 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700144 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700145}
146
Timur Iskhakov7296af12017-08-09 21:52:48 +0000147bool handleLogical(bool lval, const std::string& op, bool rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700148 COMPUTE_BINARY(||);
149 COMPUTE_BINARY(&&);
150 // Should not reach here.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700151 SHOULD_NOT_REACH() << "Could not handleLogical for "
Yifan Hongf24fa852016-09-23 11:03:15 -0700152 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700153 return false;
Yifan Hong57886972016-08-17 10:42:15 -0700154}
155
Timur Iskhakov7296af12017-08-09 21:52:48 +0000156std::unique_ptr<ConstantExpression> ConstantExpression::Zero(ScalarType::Kind kind) {
157 return ValueOf(kind, 0);
Yifan Hongf24fa852016-09-23 11:03:15 -0700158}
159
Timur Iskhakov7296af12017-08-09 21:52:48 +0000160std::unique_ptr<ConstantExpression> ConstantExpression::One(ScalarType::Kind kind) {
161 return ValueOf(kind, 1);
Yifan Hongf24fa852016-09-23 11:03:15 -0700162}
163
Timur Iskhakov7296af12017-08-09 21:52:48 +0000164std::unique_ptr<ConstantExpression> ConstantExpression::ValueOf(ScalarType::Kind kind,
165 uint64_t value) {
166 return std::make_unique<LiteralConstantExpression>(kind, value);
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700167}
168
Timur Iskhakov7296af12017-08-09 21:52:48 +0000169bool ConstantExpression::isEvaluated() const {
170 return mIsEvaluated;
171}
172
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700173LiteralConstantExpression::LiteralConstantExpression(
174 ScalarType::Kind kind, uint64_t value, const std::string& expr) {
175
176 CHECK(!expr.empty());
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700177 CHECK(isSupported(kind));
Timur Iskhakov7296af12017-08-09 21:52:48 +0000178 mTrivialDescription = true;
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700179 mExpr = expr;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000180 mValueKind = kind;
181 mValue = value;
182 mIsEvaluated = true;
Yifan Hongf24fa852016-09-23 11:03:15 -0700183}
184
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700185LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value)
186 : LiteralConstantExpression(kind, value, std::to_string(value)) {}
187
188LiteralConstantExpression* LiteralConstantExpression::tryParse(const std::string& value) {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000189 CHECK(!value.empty());
Yifan Hongf24fa852016-09-23 11:03:15 -0700190
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700191 bool isLong = false, isUnsigned = false;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000192 bool isHex = (value[0] == '0' && value.length() > 1 && (value[1] == 'x' || value[1] == 'X'));
193
194 auto rbegin = value.rbegin();
195 auto rend = value.rend();
196 for (; rbegin != rend && (*rbegin == 'u' || *rbegin == 'U' || *rbegin == 'l' || *rbegin == 'L');
197 ++rbegin) {
198 isUnsigned |= (*rbegin == 'u' || *rbegin == 'U');
199 isLong |= (*rbegin == 'l' || *rbegin == 'L');
Yifan Hong57886972016-08-17 10:42:15 -0700200 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000201 std::string newVal(value.begin(), rbegin.base());
202 CHECK(!newVal.empty());
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700203
204 uint64_t rawValue = 0;
205
206 bool parseOK = base::ParseUint(newVal, &rawValue);
207 if (!parseOK) {
208 return nullptr;
209 }
210
211 ScalarType::Kind kind;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700212
213 // guess literal type.
214 if(isLong) {
215 if(isUnsigned) // ul
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700216 kind = SK(UINT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700217 else // l
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700218 kind = SK(INT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700219 } else { // no l suffix
220 if(isUnsigned) { // u
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700221 if(rawValue <= UINT32_MAX)
222 kind = SK(UINT32);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700223 else
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700224 kind = SK(UINT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700225 } else { // no suffix
226 if(isHex) {
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700227 if(rawValue <= INT32_MAX) // rawValue always >= 0
228 kind = SK(INT32);
229 else if(rawValue <= UINT32_MAX)
230 kind = SK(UINT32);
231 else if(rawValue <= INT64_MAX) // rawValue always >= 0
232 kind = SK(INT64);
233 else if(rawValue <= UINT64_MAX)
234 kind = SK(UINT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700235 else
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700236 return nullptr;
237 } else {
238 if(rawValue <= INT32_MAX) // rawValue always >= 0
239 kind = SK(INT32);
240 else
241 kind = SK(INT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700242 }
243 }
244 }
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700245
246 return new LiteralConstantExpression(kind, rawValue, value);
Yifan Hong57886972016-08-17 10:42:15 -0700247}
248
Timur Iskhakov7296af12017-08-09 21:52:48 +0000249void LiteralConstantExpression::evaluate() {
250 // Evaluated in constructor
251 CHECK(isEvaluated());
252}
Yifan Hongf24fa852016-09-23 11:03:15 -0700253
Timur Iskhakov7296af12017-08-09 21:52:48 +0000254void UnaryConstantExpression::evaluate() {
255 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700256 CHECK(mUnary->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000257 mIsEvaluated = true;
258
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700259 mExpr = std::string("(") + mOp + mUnary->description() + ")";
260 mValueKind = mUnary->mValueKind;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000261
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700262#define CASE_UNARY(__type__) \
263 mValue = handleUnary(mOp, static_cast<__type__>(mUnary->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000264 return;
Yifan Hong57886972016-08-17 10:42:15 -0700265
Yifan Hongf24fa852016-09-23 11:03:15 -0700266 SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700267}
Yifan Hong57886972016-08-17 10:42:15 -0700268
Timur Iskhakov7296af12017-08-09 21:52:48 +0000269void BinaryConstantExpression::evaluate() {
270 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700271 CHECK(mLval->isEvaluated());
272 CHECK(mRval->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000273 mIsEvaluated = true;
274
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700275 mExpr = std::string("(") + mLval->description() + " " + mOp + " " + mRval->description() + ")";
Yifan Hong57886972016-08-17 10:42:15 -0700276
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700277 bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
278
279 // CASE 1: + - * / % | ^ & < > <= >= == !=
280 if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
281 // promoted kind for both operands.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700282 ScalarType::Kind promoted = usualArithmeticConversion(integralPromotion(mLval->mValueKind),
283 integralPromotion(mRval->mValueKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700284 // result kind.
285 mValueKind = isArithmeticOrBitflip
286 ? promoted // arithmetic or bitflip operators generates promoted type
287 : SK(BOOL); // comparison operators generates bool
288
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700289#define CASE_BINARY_COMMON(__type__) \
290 mValue = handleBinaryCommon(static_cast<__type__>(mLval->mValue), mOp, \
291 static_cast<__type__>(mRval->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000292 return;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700293
Yifan Hongf24fa852016-09-23 11:03:15 -0700294 SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700295 }
296
297 // CASE 2: << >>
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700298 std::string newOp = mOp;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700299 if(OP_IS_BIN_SHIFT) {
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700300 mValueKind = integralPromotion(mLval->mValueKind);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700301 // instead of promoting rval, simply casting it to int64 should also be good.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700302 int64_t numBits = mRval->cast<int64_t>();
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700303 if(numBits < 0) {
304 // shifting with negative number of bits is undefined in C. In HIDL it
305 // is defined as shifting into the other direction.
Timur Iskhakov7296af12017-08-09 21:52:48 +0000306 newOp = OPEQ("<<") ? std::string(">>") : std::string("<<");
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700307 numBits = -numBits;
308 }
309
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700310#define CASE_SHIFT(__type__) \
311 mValue = handleShift(static_cast<__type__>(mLval->mValue), newOp, numBits); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000312 return;
Yifan Hong57886972016-08-17 10:42:15 -0700313
Yifan Hongf24fa852016-09-23 11:03:15 -0700314 SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700315 }
Yifan Hong57886972016-08-17 10:42:15 -0700316
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700317 // CASE 3: && ||
318 if(OP_IS_BIN_LOGICAL) {
319 mValueKind = SK(BOOL);
320 // easy; everything is bool.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700321 mValue = handleLogical(mLval->mValue, mOp, mRval->mValue);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700322 return;
323 }
Yifan Hong57886972016-08-17 10:42:15 -0700324
Yifan Hongf24fa852016-09-23 11:03:15 -0700325 SHOULD_NOT_REACH();
Yifan Hong57886972016-08-17 10:42:15 -0700326}
327
Timur Iskhakov7296af12017-08-09 21:52:48 +0000328void TernaryConstantExpression::evaluate() {
329 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700330 CHECK(mCond->isEvaluated());
331 CHECK(mTrueVal->isEvaluated());
332 CHECK(mFalseVal->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000333 mIsEvaluated = true;
334
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700335 mExpr = std::string("(") + mCond->description() + "?" + mTrueVal->description() + ":" +
336 mFalseVal->description() + ")";
Yifan Hongf24fa852016-09-23 11:03:15 -0700337
Timur Iskhakov891a8662017-08-25 21:53:48 -0700338 // note: for ?:, unlike arithmetic ops, integral promotion is not processed.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700339 mValueKind = usualArithmeticConversion(mTrueVal->mValueKind, mFalseVal->mValueKind);
Yifan Hong57886972016-08-17 10:42:15 -0700340
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700341#define CASE_TERNARY(__type__) \
342 mValue = mCond->mValue ? (static_cast<__type__>(mTrueVal->mValue)) \
343 : (static_cast<__type__>(mFalseVal->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000344 return;
Yifan Hong57886972016-08-17 10:42:15 -0700345
Yifan Hongf24fa852016-09-23 11:03:15 -0700346 SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700347}
348
Timur Iskhakov7296af12017-08-09 21:52:48 +0000349void ReferenceConstantExpression::evaluate() {
350 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700351 CHECK(mReference->constExpr() != nullptr);
Timur Iskhakov7296af12017-08-09 21:52:48 +0000352
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700353 ConstantExpression* expr = mReference->constExpr();
Timur Iskhakov891a8662017-08-25 21:53:48 -0700354 CHECK(expr->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000355
356 mValueKind = expr->mValueKind;
357 mValue = expr->mValue;
358 mIsEvaluated = true;
Yifan Hong52165692016-08-12 18:06:40 -0700359}
Yifan Hong57886972016-08-17 10:42:15 -0700360
Timur Iskhakov7296af12017-08-09 21:52:48 +0000361std::unique_ptr<ConstantExpression> ConstantExpression::addOne(ScalarType::Kind baseKind) {
362 auto ret = std::make_unique<BinaryConstantExpression>(
363 this, "+", ConstantExpression::One(baseKind).release());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000364 return ret;
Yifan Hongf24fa852016-09-23 11:03:15 -0700365}
366
Timur Iskhakov7296af12017-08-09 21:52:48 +0000367const std::string& ConstantExpression::description() const {
368 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700369 return mExpr;
Yifan Hong57886972016-08-17 10:42:15 -0700370}
371
Yifan Hong5706a432016-11-02 09:44:18 -0700372bool ConstantExpression::descriptionIsTrivial() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000373 CHECK(isEvaluated());
Yifan Hong5706a432016-11-02 09:44:18 -0700374 return mTrivialDescription;
375}
376
Yifan Hongfc610cd2016-09-22 13:34:45 -0700377std::string ConstantExpression::value() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000378 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700379 return rawValue(mValueKind);
380}
381
Yifan Hongc07b2022016-11-08 12:44:24 -0800382std::string ConstantExpression::value(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000383 CHECK(isEvaluated());
Yifan Hongc07b2022016-11-08 12:44:24 -0800384 return rawValue(castKind);
385}
386
Yifan Hongf24fa852016-09-23 11:03:15 -0700387std::string ConstantExpression::cppValue() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000388 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700389 return cppValue(mValueKind);
Yifan Hong52165692016-08-12 18:06:40 -0700390}
391
Yifan Hongfc610cd2016-09-22 13:34:45 -0700392std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000393 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700394 std::string literal(rawValue(castKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700395 // this is a hack to translate
396 // enum x : int64_t { y = 1l << 63 };
397 // into
398 // enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
399 // by adding the explicit cast.
400 // Because 9223372036854775808 is uint64_t, and
401 // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
402 // be narrowed to int64_t.
403 if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
Timur Iskhakov63f39902017-08-29 15:47:29 -0700404 return strdup(("static_cast<" +
405 ScalarType(SK(INT64), nullptr /* parent */).getCppStackType() // "int64_t"
406 + ">(" + literal + "ull)")
407 .c_str());
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700408 }
Yifan Hong57886972016-08-17 10:42:15 -0700409
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700410 // add suffix if necessary.
411 if(castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
412 if(castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
Yifan Hongfc610cd2016-09-22 13:34:45 -0700413 return literal;
Yifan Hong57886972016-08-17 10:42:15 -0700414}
415
Yifan Hongf24fa852016-09-23 11:03:15 -0700416std::string ConstantExpression::javaValue() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000417 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700418 return javaValue(mValueKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700419}
420
Yifan Hongf24fa852016-09-23 11:03:15 -0700421std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000422 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700423 switch(castKind) {
424 case SK(UINT64): return rawValue(SK(INT64)) + "L";
425 case SK(INT64): return rawValue(SK(INT64)) + "L";
426 case SK(UINT32): return rawValue(SK(INT32));
427 case SK(UINT16): return rawValue(SK(INT16));
428 case SK(UINT8) : return rawValue(SK(INT8));
429 case SK(BOOL) :
430 return this->cast<bool>() ? strdup("true") : strdup("false");
431 default: break;
432 }
433 return rawValue(castKind);
434}
435
436std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000437 CHECK(isEvaluated());
Yifan Hong57886972016-08-17 10:42:15 -0700438
Yifan Hongfc610cd2016-09-22 13:34:45 -0700439#define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
Yifan Hong57886972016-08-17 10:42:15 -0700440
Yifan Hongf24fa852016-09-23 11:03:15 -0700441 SWITCH_KIND(castKind, CASE_STR, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700442}
443
Yifan Hong19ca75a2016-08-31 10:20:03 -0700444template<typename T>
445T ConstantExpression::cast() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000446 CHECK(isEvaluated());
Yifan Hong57886972016-08-17 10:42:15 -0700447
Yifan Hong19ca75a2016-08-31 10:20:03 -0700448#define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
Yifan Hong57886972016-08-17 10:42:15 -0700449
Yifan Hongf24fa852016-09-23 11:03:15 -0700450 SWITCH_KIND(mValueKind, CASE_CAST_T, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700451}
452
Yifan Honge77ca132016-09-27 10:49:05 -0700453size_t ConstantExpression::castSizeT() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000454 CHECK(isEvaluated());
Yifan Honge77ca132016-09-27 10:49:05 -0700455 return this->cast<size_t>();
456}
457
Timur Iskhakova6d33882017-09-01 13:02:09 -0700458bool ConstantExpression::isReferenceConstantExpression() const {
459 return false;
460}
461
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700462std::vector<ConstantExpression*> ConstantExpression::getConstantExpressions() {
463 const auto& constRet = static_cast<const ConstantExpression*>(this)->getConstantExpressions();
464 std::vector<ConstantExpression*> ret(constRet.size());
465 std::transform(constRet.begin(), constRet.end(), ret.begin(),
466 [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
467 return ret;
468}
469
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700470std::vector<Reference<LocalIdentifier>*> ConstantExpression::getReferences() {
471 const auto& constRet = static_cast<const ConstantExpression*>(this)->getReferences();
472 std::vector<Reference<LocalIdentifier>*> ret(constRet.size());
473 std::transform(constRet.begin(), constRet.end(), ret.begin(),
474 [](const auto* ce) { return const_cast<Reference<LocalIdentifier>*>(ce); });
475 return ret;
476}
477
478std::vector<const Reference<LocalIdentifier>*> ConstantExpression::getReferences() const {
479 return {};
480}
481
Timur Iskhakov891a8662017-08-25 21:53:48 -0700482status_t ConstantExpression::recursivePass(const std::function<status_t(ConstantExpression*)>& func,
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700483 std::unordered_set<const ConstantExpression*>* visited,
484 bool processBeforeDependencies) {
Timur Iskhakov35930c42017-08-28 18:49:54 -0700485 if (mIsPostParseCompleted) return OK;
486
Timur Iskhakov891a8662017-08-25 21:53:48 -0700487 if (visited->find(this) != visited->end()) return OK;
488 visited->insert(this);
489
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700490 if (processBeforeDependencies) {
491 status_t err = func(this);
492 if (err != OK) return err;
493 }
494
Timur Iskhakov891a8662017-08-25 21:53:48 -0700495 for (auto* nextCE : getConstantExpressions()) {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700496 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
Timur Iskhakov891a8662017-08-25 21:53:48 -0700497 if (err != OK) return err;
498 }
499
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700500 for (auto* nextRef : getReferences()) {
501 auto* nextCE = nextRef->shallowGet()->constExpr();
502 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700503 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700504 if (err != OK) return err;
505 }
506
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700507 if (!processBeforeDependencies) {
508 status_t err = func(this);
509 if (err != OK) return err;
510 }
Timur Iskhakov891a8662017-08-25 21:53:48 -0700511
512 return OK;
513}
514
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700515status_t ConstantExpression::recursivePass(
516 const std::function<status_t(const ConstantExpression*)>& func,
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700517 std::unordered_set<const ConstantExpression*>* visited, bool processBeforeDependencies) const {
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700518 if (mIsPostParseCompleted) return OK;
519
520 if (visited->find(this) != visited->end()) return OK;
521 visited->insert(this);
522
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700523 if (processBeforeDependencies) {
524 status_t err = func(this);
525 if (err != OK) return err;
526 }
527
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700528 for (const auto* nextCE : getConstantExpressions()) {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700529 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700530 if (err != OK) return err;
531 }
532
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700533 for (const auto* nextRef : getReferences()) {
534 const auto* nextCE = nextRef->shallowGet()->constExpr();
535 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700536 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700537 if (err != OK) return err;
538 }
539
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700540 if (!processBeforeDependencies) {
541 status_t err = func(this);
542 if (err != OK) return err;
543 }
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700544
545 return OK;
546}
547
Timur Iskhakova6d33882017-09-01 13:02:09 -0700548ConstantExpression::CheckAcyclicStatus::CheckAcyclicStatus(
549 status_t status, const ConstantExpression* cycleEnd,
550 const ReferenceConstantExpression* lastReference)
551 : status(status), cycleEnd(cycleEnd), lastReference(lastReference) {
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700552 CHECK(cycleEnd == nullptr || status != OK);
Timur Iskhakova6d33882017-09-01 13:02:09 -0700553 CHECK((cycleEnd == nullptr) == (lastReference == nullptr));
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700554}
555
556ConstantExpression::CheckAcyclicStatus ConstantExpression::checkAcyclic(
557 std::unordered_set<const ConstantExpression*>* visited,
558 std::unordered_set<const ConstantExpression*>* stack) const {
559 if (stack->find(this) != stack->end()) {
Timur Iskhakova6d33882017-09-01 13:02:09 -0700560 CHECK(isReferenceConstantExpression())
561 << "Only reference constant expression could be the cycle end";
562
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700563 std::cerr << "ERROR: Cyclic declaration:\n";
Timur Iskhakova6d33882017-09-01 13:02:09 -0700564 return CheckAcyclicStatus(UNKNOWN_ERROR, this,
565 static_cast<const ReferenceConstantExpression*>(this));
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700566 }
567
568 if (visited->find(this) != visited->end()) return CheckAcyclicStatus(OK);
569 visited->insert(this);
570 stack->insert(this);
571
572 for (const auto* nextCE : getConstantExpressions()) {
573 auto err = nextCE->checkAcyclic(visited, stack);
574 if (err.status != OK) {
575 return err;
576 }
577 }
578
579 for (const auto* nextRef : getReferences()) {
580 const auto* nextCE = nextRef->shallowGet()->constExpr();
581 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
582 auto err = nextCE->checkAcyclic(visited, stack);
583
584 if (err.status != OK) {
585 if (err.cycleEnd == nullptr) return err;
586
587 // Only ReferenceConstantExpression has references,
Timur Iskhakova6d33882017-09-01 13:02:09 -0700588 CHECK(isReferenceConstantExpression())
589 << "Only reference constant expression could have refereneces";
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700590
Timur Iskhakova6d33882017-09-01 13:02:09 -0700591 // mExpr is defined explicitly before evaluation
592 std::cerr << " '" << err.lastReference->mExpr << "' in '" << mExpr << "' at "
593 << nextRef->location() << "\n";
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700594
595 if (err.cycleEnd == this) {
596 return CheckAcyclicStatus(err.status);
597 }
Timur Iskhakova6d33882017-09-01 13:02:09 -0700598 return CheckAcyclicStatus(err.status, err.cycleEnd,
599 static_cast<const ReferenceConstantExpression*>(this));
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700600 }
601 }
602
603 CHECK(stack->find(this) != stack->end());
604 stack->erase(this);
605 return CheckAcyclicStatus(OK);
606}
607
Timur Iskhakov35930c42017-08-28 18:49:54 -0700608void ConstantExpression::setPostParseCompleted() {
609 CHECK(!mIsPostParseCompleted);
610 mIsPostParseCompleted = true;
611}
612
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700613std::vector<const ConstantExpression*> LiteralConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700614 return {};
615}
616
Timur Iskhakov7296af12017-08-09 21:52:48 +0000617UnaryConstantExpression::UnaryConstantExpression(const std::string& op, ConstantExpression* value)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700618 : mUnary(value), mOp(op) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000619
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700620std::vector<const ConstantExpression*> UnaryConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700621 return {mUnary};
622}
623
Timur Iskhakov7296af12017-08-09 21:52:48 +0000624BinaryConstantExpression::BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
625 ConstantExpression* rval)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700626 : mLval(lval), mRval(rval), mOp(op) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000627
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700628std::vector<const ConstantExpression*> BinaryConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700629 return {mLval, mRval};
630}
631
Timur Iskhakov7296af12017-08-09 21:52:48 +0000632TernaryConstantExpression::TernaryConstantExpression(ConstantExpression* cond,
633 ConstantExpression* trueVal,
634 ConstantExpression* falseVal)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700635 : mCond(cond), mTrueVal(trueVal), mFalseVal(falseVal) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000636
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700637std::vector<const ConstantExpression*> TernaryConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700638 return {mCond, mTrueVal, mFalseVal};
639}
640
Timur Iskhakov7296af12017-08-09 21:52:48 +0000641ReferenceConstantExpression::ReferenceConstantExpression(const Reference<LocalIdentifier>& value,
642 const std::string& expr)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700643 : mReference(value) {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000644 mExpr = expr;
Timur Iskhakov505e5612017-08-27 18:26:48 -0700645 mTrivialDescription = mExpr.empty();
Timur Iskhakov7296af12017-08-09 21:52:48 +0000646}
647
Timur Iskhakova6d33882017-09-01 13:02:09 -0700648bool ReferenceConstantExpression::isReferenceConstantExpression() const {
649 return true;
650}
651
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700652std::vector<const ConstantExpression*> ReferenceConstantExpression::getConstantExpressions() const {
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700653 // Returns reference instead
654 return {};
655}
656
657std::vector<const Reference<LocalIdentifier>*> ReferenceConstantExpression::getReferences() const {
658 return {&mReference};
Timur Iskhakov891a8662017-08-25 21:53:48 -0700659}
660
Yifan Hong57886972016-08-17 10:42:15 -0700661/*
662
663Evaluating expressions in HIDL language
664
665The following rules are mostly like that in:
666http://en.cppreference.com/w/cpp/language/operator_arithmetic
667http://en.cppreference.com/w/cpp/language/operator_logical
668http://en.cppreference.com/w/cpp/language/operator_comparison
669http://en.cppreference.com/w/cpp/language/operator_other
670
671The type of literal is the first type which the value
672can fit from the list of types depending on the suffix and bases.
673
674suffix decimal bases hexadecimal bases
675no suffix int32_t int32_t
676 int64_t uint32_t
677 int64_t
678 uint64_t
679
680u/U uint32_t (same as left)
681 uint64_t
682
683l/L int64_t int64_t
684
685ul/UL/uL/Ul uint64_t uint64_t
686
687
688Note: There are no negative integer literals.
689 -1 is the unary minus applied to 1.
690
691Unary arithmetic and bitwise operators (~ + -):
692 don't change the type of the argument.
693 (so -1u = -(1u) has type uint32_t)
694
695Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
6961. Integral promotion is first applied on both sides.
6972. If both operands have the same type, no promotion is necessary.
6983. Usual arithmetic conversions.
699
700Integral promotion: if an operand is of a type with less than 32 bits,
701(including bool), it is promoted to int32_t.
702
703Usual arithmetic conversions:
7041. If operands are both signed or both unsigned, lesser conversion rank is
705 converted to greater conversion rank.
7062. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
7073. Otherwise, if signed's type can hold all values in unsigned's type,
708 -> signed's type
7094. Otherwise, both converted to the unsigned counterpart of the signed operand's
710 type.
711rank: bool < int8_t < int16_t < int32_t < int64_t
712
713
714Shift operators (<< >>):
7151. Integral promotion is applied on both sides.
7162. For unsigned a, a << b discards bits that shifts out.
717 For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
718 For signed negative a, a << b gives error.
7193. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
720 For signed negative a, a >> b discards bits that shifts out, and the signed
721 bit gets extended. ("arithmetic right shift")
7224. Shifting with negative number of bits is undefined. (Currently, the
723 parser will shift into the other direction. This behavior may change.)
7245. Shifting with number of bits exceeding the width of the type is undefined.
725 (Currently, 1 << 32 == 1. This behavior may change.)
726
727Logical operators (!, &&, ||):
7281. Convert first operand to bool. (true if non-zero, false otherwise)
7292. If short-circuited, return the result as type bool, value 1 or 0.
7303. Otherwise, convert second operand to bool, evaluate the result, and return
731 the result in the same fashion.
732
733Arithmetic comparison operators (< > <= >= == !=):
7341. Promote operands in the same way as binary arithmetic and bitwise operators.
735 (Integral promotion + Usual arithmetic conversions)
7362. Return type bool, value 0 or 1 the same way as logical operators.
737
738Ternary conditional operator (?:):
7391. Evaluate the conditional and evaluate the operands.
7402. Return type of expression is the type under usual arithmetic conversions on
741 the second and third operand. (No integral promotions necessary.)
742
743*/
744
Yifan Hong52165692016-08-12 18:06:40 -0700745} // namespace android
746