1 /*
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
17 #include "ConstantExpression.h"
18
19 #include <android-base/logging.h>
20 #include <android-base/parseint.h>
21 #include <stdio.h>
22 #include <algorithm>
23 #include <iostream>
24 #include <sstream>
25 #include <string>
26
27 #include "EnumType.h"
28 #include "Scope.h" // LocalIdentifier
29
30 // The macros are really nasty here. Consider removing
31 // as many macros as possible.
32
33 #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;
36 #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__
42 #define SHOULD_NOT_REACH() CHECK(false) << __LINE__ << ": should not reach here: "
43
44 // NOLINT to suppress missing parentheses warnings about __def__.
45 #define SWITCH_KIND(__cond__, __action__, __def__) \
46 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) \
56 default: __def__ /* NOLINT */ \
57 }
58
59 namespace android {
60
isSupported(ScalarType::Kind kind)61 static inline bool isSupported(ScalarType::Kind kind) {
62 return SK(BOOL) == kind || ScalarType(kind, nullptr /* parent */).isValidEnumStorageType();
63 }
64
65 /* See docs at the end for details on integral promotion. */
integralPromotion(ScalarType::Kind in)66 ScalarType::Kind integralPromotion(ScalarType::Kind in) {
67 return SK(INT32) < in ? in : SK(INT32); // note that KIND_INT32 < KIND_UINT32
68 }
69
70 /* See docs at the end for details on usual arithmetic conversion. */
usualArithmeticConversion(ScalarType::Kind lft,ScalarType::Kind rgt)71 ScalarType::Kind usualArithmeticConversion(ScalarType::Kind lft,
72 ScalarType::Kind rgt) {
73 CHECK(isSupported(lft) && isSupported(rgt));
74 // 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;
87
88 // 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 CHECK(false) << "Could not do usual arithmetic conversion for type " << lft << "and" << rgt;
91 switch(signedRank) {
92 case SK(INT8): return SK(UINT8);
93 case SK(INT16): return SK(UINT16);
94 case SK(INT32): return SK(UINT32);
95 case SK(INT64): return SK(UINT64);
96 default: return SK(UINT64);
97 }
98 }
99
100 template <class T>
handleUnary(const std::string & op,T val)101 T handleUnary(const std::string& op, T val) {
102 COMPUTE_UNARY(+)
103 COMPUTE_UNARY(-)
104 COMPUTE_UNARY(!)
105 COMPUTE_UNARY(~)
106 // Should not reach here.
107 SHOULD_NOT_REACH() << "Could not handleUnary for " << op << " " << val;
108 return static_cast<T>(0xdeadbeef);
109 }
110
111 template <class T>
handleBinaryCommon(T lval,const std::string & op,T rval)112 T handleBinaryCommon(T lval, const std::string& op, T rval) {
113 COMPUTE_BINARY(+)
114 COMPUTE_BINARY(-)
115 COMPUTE_BINARY(*)
116 COMPUTE_BINARY(/)
117 COMPUTE_BINARY(%)
118 COMPUTE_BINARY(|)
119 COMPUTE_BINARY(^)
120 COMPUTE_BINARY(&)
121 // comparison operators: return 0 or 1 by nature.
122 COMPUTE_BINARY(==)
123 COMPUTE_BINARY(!=)
124 COMPUTE_BINARY(<)
125 COMPUTE_BINARY(>)
126 COMPUTE_BINARY(<=)
127 COMPUTE_BINARY(>=)
128 // Should not reach here.
129 SHOULD_NOT_REACH() << "Could not handleBinaryCommon for "
130 << lval << " " << op << " " << rval;
131 return static_cast<T>(0xdeadbeef);
132 }
133
134 template <class T>
handleShift(T lval,const std::string & op,int64_t rval)135 T handleShift(T lval, const std::string& op, int64_t rval) {
136 // just cast rval to int64_t and it should fit.
137 COMPUTE_BINARY(>>)
138 COMPUTE_BINARY(<<)
139 // Should not reach here.
140 SHOULD_NOT_REACH() << "Could not handleShift for "
141 << lval << " " << op << " " << rval;
142 return static_cast<T>(0xdeadbeef);
143 }
144
handleLogical(bool lval,const std::string & op,bool rval)145 bool handleLogical(bool lval, const std::string& op, bool rval) {
146 COMPUTE_BINARY(||);
147 COMPUTE_BINARY(&&);
148 // Should not reach here.
149 SHOULD_NOT_REACH() << "Could not handleLogical for "
150 << lval << " " << op << " " << rval;
151 return false;
152 }
153
Zero(ScalarType::Kind kind)154 std::unique_ptr<ConstantExpression> ConstantExpression::Zero(ScalarType::Kind kind) {
155 return ValueOf(kind, 0);
156 }
157
One(ScalarType::Kind kind)158 std::unique_ptr<ConstantExpression> ConstantExpression::One(ScalarType::Kind kind) {
159 return ValueOf(kind, 1);
160 }
161
ValueOf(ScalarType::Kind kind,uint64_t value)162 std::unique_ptr<ConstantExpression> ConstantExpression::ValueOf(ScalarType::Kind kind,
163 uint64_t value) {
164 return std::make_unique<LiteralConstantExpression>(kind, value);
165 }
166
isEvaluated() const167 bool ConstantExpression::isEvaluated() const {
168 return mIsEvaluated;
169 }
170
LiteralConstantExpression(ScalarType::Kind kind,uint64_t value,const std::string & expr)171 LiteralConstantExpression::LiteralConstantExpression(
172 ScalarType::Kind kind, uint64_t value, const std::string& expr) {
173
174 CHECK(!expr.empty());
175 CHECK(isSupported(kind));
176 mTrivialDescription = true;
177 mExpr = expr;
178 mValueKind = kind;
179 mValue = value;
180 mIsEvaluated = true;
181 }
182
LiteralConstantExpression(ScalarType::Kind kind,uint64_t value)183 LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value)
184 : LiteralConstantExpression(kind, value, std::to_string(value)) {}
185
tryParse(const std::string & value)186 LiteralConstantExpression* LiteralConstantExpression::tryParse(const std::string& value) {
187 CHECK(!value.empty());
188
189 bool isLong = false, isUnsigned = false;
190 bool isHex = (value[0] == '0' && value.length() > 1 && (value[1] == 'x' || value[1] == 'X'));
191
192 auto rbegin = value.rbegin();
193 auto rend = value.rend();
194 for (; rbegin != rend && (*rbegin == 'u' || *rbegin == 'U' || *rbegin == 'l' || *rbegin == 'L');
195 ++rbegin) {
196 isUnsigned |= (*rbegin == 'u' || *rbegin == 'U');
197 isLong |= (*rbegin == 'l' || *rbegin == 'L');
198 }
199 std::string newVal(value.begin(), rbegin.base());
200 CHECK(!newVal.empty());
201
202 uint64_t rawValue = 0;
203
204 bool parseOK = base::ParseUint(newVal, &rawValue);
205 if (!parseOK) {
206 return nullptr;
207 }
208
209 ScalarType::Kind kind;
210
211 // guess literal type.
212 if(isLong) {
213 if(isUnsigned) // ul
214 kind = SK(UINT64);
215 else // l
216 kind = SK(INT64);
217 } else { // no l suffix
218 if(isUnsigned) { // u
219 if(rawValue <= UINT32_MAX)
220 kind = SK(UINT32);
221 else
222 kind = SK(UINT64);
223 } else { // no suffix
224 if(isHex) {
225 if(rawValue <= INT32_MAX) // rawValue always >= 0
226 kind = SK(INT32);
227 else if(rawValue <= UINT32_MAX)
228 kind = SK(UINT32);
229 else if(rawValue <= INT64_MAX) // rawValue always >= 0
230 kind = SK(INT64);
231 else if(rawValue <= UINT64_MAX)
232 kind = SK(UINT64);
233 else
234 return nullptr;
235 } else {
236 if(rawValue <= INT32_MAX) // rawValue always >= 0
237 kind = SK(INT32);
238 else
239 kind = SK(INT64);
240 }
241 }
242 }
243
244 return new LiteralConstantExpression(kind, rawValue, value);
245 }
246
evaluate()247 void LiteralConstantExpression::evaluate() {
248 // Evaluated in constructor
249 CHECK(isEvaluated());
250 }
251
evaluate()252 void UnaryConstantExpression::evaluate() {
253 if (isEvaluated()) return;
254 CHECK(mUnary->isEvaluated());
255 mIsEvaluated = true;
256
257 mExpr = std::string("(") + mOp + mUnary->description() + ")";
258 mValueKind = mUnary->mValueKind;
259
260 #define CASE_UNARY(__type__) \
261 mValue = handleUnary(mOp, static_cast<__type__>(mUnary->mValue)); \
262 return;
263
264 SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
265 }
266
evaluate()267 void BinaryConstantExpression::evaluate() {
268 if (isEvaluated()) return;
269 CHECK(mLval->isEvaluated());
270 CHECK(mRval->isEvaluated());
271 mIsEvaluated = true;
272
273 mExpr = std::string("(") + mLval->description() + " " + mOp + " " + mRval->description() + ")";
274
275 bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
276
277 // CASE 1: + - * / % | ^ & < > <= >= == !=
278 if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
279 // promoted kind for both operands.
280 ScalarType::Kind promoted = usualArithmeticConversion(integralPromotion(mLval->mValueKind),
281 integralPromotion(mRval->mValueKind));
282 // result kind.
283 mValueKind = isArithmeticOrBitflip
284 ? promoted // arithmetic or bitflip operators generates promoted type
285 : SK(BOOL); // comparison operators generates bool
286
287 #define CASE_BINARY_COMMON(__type__) \
288 mValue = handleBinaryCommon(static_cast<__type__>(mLval->mValue), mOp, \
289 static_cast<__type__>(mRval->mValue)); \
290 return;
291
292 SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
293 }
294
295 // CASE 2: << >>
296 std::string newOp = mOp;
297 if(OP_IS_BIN_SHIFT) {
298 mValueKind = integralPromotion(mLval->mValueKind);
299 // instead of promoting rval, simply casting it to int64 should also be good.
300 int64_t numBits = mRval->cast<int64_t>();
301 if(numBits < 0) {
302 // shifting with negative number of bits is undefined in C. In HIDL it
303 // is defined as shifting into the other direction.
304 newOp = OPEQ("<<") ? std::string(">>") : std::string("<<");
305 numBits = -numBits;
306 }
307
308 #define CASE_SHIFT(__type__) \
309 mValue = handleShift(static_cast<__type__>(mLval->mValue), newOp, numBits); \
310 return;
311
312 SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
313 }
314
315 // CASE 3: && ||
316 if(OP_IS_BIN_LOGICAL) {
317 mValueKind = SK(BOOL);
318 // easy; everything is bool.
319 mValue = handleLogical(mLval->mValue, mOp, mRval->mValue);
320 return;
321 }
322
323 SHOULD_NOT_REACH();
324 }
325
evaluate()326 void TernaryConstantExpression::evaluate() {
327 if (isEvaluated()) return;
328 CHECK(mCond->isEvaluated());
329 CHECK(mTrueVal->isEvaluated());
330 CHECK(mFalseVal->isEvaluated());
331 mIsEvaluated = true;
332
333 mExpr = std::string("(") + mCond->description() + "?" + mTrueVal->description() + ":" +
334 mFalseVal->description() + ")";
335
336 // note: for ?:, unlike arithmetic ops, integral promotion is not processed.
337 mValueKind = usualArithmeticConversion(mTrueVal->mValueKind, mFalseVal->mValueKind);
338
339 #define CASE_TERNARY(__type__) \
340 mValue = mCond->mValue ? (static_cast<__type__>(mTrueVal->mValue)) \
341 : (static_cast<__type__>(mFalseVal->mValue)); \
342 return;
343
344 SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
345 }
346
evaluate()347 void ReferenceConstantExpression::evaluate() {
348 if (isEvaluated()) return;
349 CHECK(mReference->constExpr() != nullptr);
350
351 ConstantExpression* expr = mReference->constExpr();
352 CHECK(expr->isEvaluated());
353
354 mValueKind = expr->mValueKind;
355 mValue = expr->mValue;
356 mIsEvaluated = true;
357 }
358
addOne(ScalarType::Kind baseKind)359 std::unique_ptr<ConstantExpression> ConstantExpression::addOne(ScalarType::Kind baseKind) {
360 auto ret = std::make_unique<BinaryConstantExpression>(
361 this, "+", ConstantExpression::One(baseKind).release());
362 return ret;
363 }
364
description() const365 const std::string& ConstantExpression::description() const {
366 CHECK(isEvaluated());
367 return mExpr;
368 }
369
descriptionIsTrivial() const370 bool ConstantExpression::descriptionIsTrivial() const {
371 CHECK(isEvaluated());
372 return mTrivialDescription;
373 }
374
value() const375 std::string ConstantExpression::value() const {
376 CHECK(isEvaluated());
377 return rawValue(mValueKind);
378 }
379
value(ScalarType::Kind castKind) const380 std::string ConstantExpression::value(ScalarType::Kind castKind) const {
381 CHECK(isEvaluated());
382 return rawValue(castKind);
383 }
384
cppValue() const385 std::string ConstantExpression::cppValue() const {
386 CHECK(isEvaluated());
387 return cppValue(mValueKind);
388 }
389
cppValue(ScalarType::Kind castKind) const390 std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
391 CHECK(isEvaluated());
392 std::string literal(rawValue(castKind));
393 // this is a hack to translate
394 // enum x : int64_t { y = 1l << 63 };
395 // into
396 // enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
397 // by adding the explicit cast.
398 // Because 9223372036854775808 is uint64_t, and
399 // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
400 // be narrowed to int64_t.
401 if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
402 return "static_cast<" +
403 ScalarType(SK(INT64), nullptr /* parent */).getCppStackType() // "int64_t"
404 + ">(" + literal + "ull)";
405 }
406
407 // add suffix if necessary.
408 if(castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
409 if(castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
410 return literal;
411 }
412
javaValue() const413 std::string ConstantExpression::javaValue() const {
414 CHECK(isEvaluated());
415 return javaValue(mValueKind);
416 }
417
javaValue(ScalarType::Kind castKind) const418 std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
419 CHECK(isEvaluated());
420 switch(castKind) {
421 case SK(UINT64): return rawValue(SK(INT64)) + "L";
422 case SK(INT64): return rawValue(SK(INT64)) + "L";
423 case SK(UINT32): return rawValue(SK(INT32));
424 case SK(UINT16): return rawValue(SK(INT16));
425 case SK(UINT8) : return rawValue(SK(INT8));
426 case SK(BOOL) :
427 return this->cast<bool>() ? "true" : "false";
428 default: break;
429 }
430 return rawValue(castKind);
431 }
432
rawValue(ScalarType::Kind castKind) const433 std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
434 CHECK(isEvaluated());
435
436 #define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
437
438 SWITCH_KIND(castKind, CASE_STR, SHOULD_NOT_REACH(); return 0; );
439 }
440
441 template<typename T>
cast() const442 T ConstantExpression::cast() const {
443 CHECK(isEvaluated());
444
445 #define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
446
447 SWITCH_KIND(mValueKind, CASE_CAST_T, SHOULD_NOT_REACH(); return 0; );
448 }
449
castSizeT() const450 size_t ConstantExpression::castSizeT() const {
451 CHECK(isEvaluated());
452 return this->cast<size_t>();
453 }
454
isReferenceConstantExpression() const455 bool ConstantExpression::isReferenceConstantExpression() const {
456 return false;
457 }
458
getConstantExpressions()459 std::vector<ConstantExpression*> ConstantExpression::getConstantExpressions() {
460 const auto& constRet = static_cast<const ConstantExpression*>(this)->getConstantExpressions();
461 std::vector<ConstantExpression*> ret(constRet.size());
462 std::transform(constRet.begin(), constRet.end(), ret.begin(),
463 [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
464 return ret;
465 }
466
getReferences()467 std::vector<Reference<LocalIdentifier>*> ConstantExpression::getReferences() {
468 const auto& constRet = static_cast<const ConstantExpression*>(this)->getReferences();
469 std::vector<Reference<LocalIdentifier>*> ret(constRet.size());
470 std::transform(constRet.begin(), constRet.end(), ret.begin(),
471 [](const auto* ce) { return const_cast<Reference<LocalIdentifier>*>(ce); });
472 return ret;
473 }
474
getReferences() const475 std::vector<const Reference<LocalIdentifier>*> ConstantExpression::getReferences() const {
476 return {};
477 }
478
recursivePass(const std::function<status_t (ConstantExpression *)> & func,std::unordered_set<const ConstantExpression * > * visited,bool processBeforeDependencies)479 status_t ConstantExpression::recursivePass(const std::function<status_t(ConstantExpression*)>& func,
480 std::unordered_set<const ConstantExpression*>* visited,
481 bool processBeforeDependencies) {
482 if (mIsPostParseCompleted) return OK;
483
484 if (visited->find(this) != visited->end()) return OK;
485 visited->insert(this);
486
487 if (processBeforeDependencies) {
488 status_t err = func(this);
489 if (err != OK) return err;
490 }
491
492 for (auto* nextCE : getConstantExpressions()) {
493 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
494 if (err != OK) return err;
495 }
496
497 for (auto* nextRef : getReferences()) {
498 auto* nextCE = nextRef->shallowGet()->constExpr();
499 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
500 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
501 if (err != OK) return err;
502 }
503
504 if (!processBeforeDependencies) {
505 status_t err = func(this);
506 if (err != OK) return err;
507 }
508
509 return OK;
510 }
511
recursivePass(const std::function<status_t (const ConstantExpression *)> & func,std::unordered_set<const ConstantExpression * > * visited,bool processBeforeDependencies) const512 status_t ConstantExpression::recursivePass(
513 const std::function<status_t(const ConstantExpression*)>& func,
514 std::unordered_set<const ConstantExpression*>* visited, bool processBeforeDependencies) const {
515 if (mIsPostParseCompleted) return OK;
516
517 if (visited->find(this) != visited->end()) return OK;
518 visited->insert(this);
519
520 if (processBeforeDependencies) {
521 status_t err = func(this);
522 if (err != OK) return err;
523 }
524
525 for (const auto* nextCE : getConstantExpressions()) {
526 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
527 if (err != OK) return err;
528 }
529
530 for (const auto* nextRef : getReferences()) {
531 const auto* nextCE = nextRef->shallowGet()->constExpr();
532 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
533 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
534 if (err != OK) return err;
535 }
536
537 if (!processBeforeDependencies) {
538 status_t err = func(this);
539 if (err != OK) return err;
540 }
541
542 return OK;
543 }
544
CheckAcyclicStatus(status_t status,const ConstantExpression * cycleEnd,const ReferenceConstantExpression * lastReference)545 ConstantExpression::CheckAcyclicStatus::CheckAcyclicStatus(
546 status_t status, const ConstantExpression* cycleEnd,
547 const ReferenceConstantExpression* lastReference)
548 : status(status), cycleEnd(cycleEnd), lastReference(lastReference) {
549 CHECK(cycleEnd == nullptr || status != OK);
550 CHECK((cycleEnd == nullptr) == (lastReference == nullptr));
551 }
552
checkAcyclic(std::unordered_set<const ConstantExpression * > * visited,std::unordered_set<const ConstantExpression * > * stack) const553 ConstantExpression::CheckAcyclicStatus ConstantExpression::checkAcyclic(
554 std::unordered_set<const ConstantExpression*>* visited,
555 std::unordered_set<const ConstantExpression*>* stack) const {
556 if (stack->find(this) != stack->end()) {
557 CHECK(isReferenceConstantExpression())
558 << "Only reference constant expression could be the cycle end";
559
560 std::cerr << "ERROR: Cyclic declaration:\n";
561 return CheckAcyclicStatus(UNKNOWN_ERROR, this,
562 static_cast<const ReferenceConstantExpression*>(this));
563 }
564
565 if (visited->find(this) != visited->end()) return CheckAcyclicStatus(OK);
566 visited->insert(this);
567 stack->insert(this);
568
569 for (const auto* nextCE : getConstantExpressions()) {
570 auto err = nextCE->checkAcyclic(visited, stack);
571 if (err.status != OK) {
572 return err;
573 }
574 }
575
576 for (const auto* nextRef : getReferences()) {
577 const auto* nextCE = nextRef->shallowGet()->constExpr();
578 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
579 auto err = nextCE->checkAcyclic(visited, stack);
580
581 if (err.status != OK) {
582 if (err.cycleEnd == nullptr) return err;
583
584 // Only ReferenceConstantExpression has references,
585 CHECK(isReferenceConstantExpression())
586 << "Only reference constant expression could have refereneces";
587
588 // mExpr is defined explicitly before evaluation
589 std::cerr << " '" << err.lastReference->mExpr << "' in '" << mExpr << "' at "
590 << nextRef->location() << "\n";
591
592 if (err.cycleEnd == this) {
593 return CheckAcyclicStatus(err.status);
594 }
595 return CheckAcyclicStatus(err.status, err.cycleEnd,
596 static_cast<const ReferenceConstantExpression*>(this));
597 }
598 }
599
600 CHECK(stack->find(this) != stack->end());
601 stack->erase(this);
602 return CheckAcyclicStatus(OK);
603 }
604
setPostParseCompleted()605 void ConstantExpression::setPostParseCompleted() {
606 CHECK(!mIsPostParseCompleted);
607 mIsPostParseCompleted = true;
608 }
609
getConstantExpressions() const610 std::vector<const ConstantExpression*> LiteralConstantExpression::getConstantExpressions() const {
611 return {};
612 }
613
UnaryConstantExpression(const std::string & op,ConstantExpression * value)614 UnaryConstantExpression::UnaryConstantExpression(const std::string& op, ConstantExpression* value)
615 : mUnary(value), mOp(op) {}
616
getConstantExpressions() const617 std::vector<const ConstantExpression*> UnaryConstantExpression::getConstantExpressions() const {
618 return {mUnary};
619 }
620
BinaryConstantExpression(ConstantExpression * lval,const std::string & op,ConstantExpression * rval)621 BinaryConstantExpression::BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
622 ConstantExpression* rval)
623 : mLval(lval), mRval(rval), mOp(op) {}
624
getConstantExpressions() const625 std::vector<const ConstantExpression*> BinaryConstantExpression::getConstantExpressions() const {
626 return {mLval, mRval};
627 }
628
TernaryConstantExpression(ConstantExpression * cond,ConstantExpression * trueVal,ConstantExpression * falseVal)629 TernaryConstantExpression::TernaryConstantExpression(ConstantExpression* cond,
630 ConstantExpression* trueVal,
631 ConstantExpression* falseVal)
632 : mCond(cond), mTrueVal(trueVal), mFalseVal(falseVal) {}
633
getConstantExpressions() const634 std::vector<const ConstantExpression*> TernaryConstantExpression::getConstantExpressions() const {
635 return {mCond, mTrueVal, mFalseVal};
636 }
637
ReferenceConstantExpression(const Reference<LocalIdentifier> & value,const std::string & expr)638 ReferenceConstantExpression::ReferenceConstantExpression(const Reference<LocalIdentifier>& value,
639 const std::string& expr)
640 : mReference(value) {
641 mExpr = expr;
642 mTrivialDescription = mExpr.empty();
643 }
644
isReferenceConstantExpression() const645 bool ReferenceConstantExpression::isReferenceConstantExpression() const {
646 return true;
647 }
648
getConstantExpressions() const649 std::vector<const ConstantExpression*> ReferenceConstantExpression::getConstantExpressions() const {
650 // Returns reference instead
651 return {};
652 }
653
getReferences() const654 std::vector<const Reference<LocalIdentifier>*> ReferenceConstantExpression::getReferences() const {
655 return {&mReference};
656 }
657
658 /*
659
660 Evaluating expressions in HIDL language
661
662 The following rules are mostly like that in:
663 http://en.cppreference.com/w/cpp/language/operator_arithmetic
664 http://en.cppreference.com/w/cpp/language/operator_logical
665 http://en.cppreference.com/w/cpp/language/operator_comparison
666 http://en.cppreference.com/w/cpp/language/operator_other
667
668 The type of literal is the first type which the value
669 can fit from the list of types depending on the suffix and bases.
670
671 suffix decimal bases hexadecimal bases
672 no suffix int32_t int32_t
673 int64_t uint32_t
674 int64_t
675 uint64_t
676
677 u/U uint32_t (same as left)
678 uint64_t
679
680 l/L int64_t int64_t
681
682 ul/UL/uL/Ul uint64_t uint64_t
683
684
685 Note: There are no negative integer literals.
686 -1 is the unary minus applied to 1.
687
688 Unary arithmetic and bitwise operators (~ + -):
689 don't change the type of the argument.
690 (so -1u = -(1u) has type uint32_t)
691
692 Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
693 1. Integral promotion is first applied on both sides.
694 2. If both operands have the same type, no promotion is necessary.
695 3. Usual arithmetic conversions.
696
697 Integral promotion: if an operand is of a type with less than 32 bits,
698 (including bool), it is promoted to int32_t.
699
700 Usual arithmetic conversions:
701 1. If operands are both signed or both unsigned, lesser conversion rank is
702 converted to greater conversion rank.
703 2. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
704 3. Otherwise, if signed's type can hold all values in unsigned's type,
705 -> signed's type
706 4. Otherwise, both converted to the unsigned counterpart of the signed operand's
707 type.
708 rank: bool < int8_t < int16_t < int32_t < int64_t
709
710
711 Shift operators (<< >>):
712 1. Integral promotion is applied on both sides.
713 2. For unsigned a, a << b discards bits that shifts out.
714 For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
715 For signed negative a, a << b gives error.
716 3. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
717 For signed negative a, a >> b discards bits that shifts out, and the signed
718 bit gets extended. ("arithmetic right shift")
719 4. Shifting with negative number of bits is undefined. (Currently, the
720 parser will shift into the other direction. This behavior may change.)
721 5. Shifting with number of bits exceeding the width of the type is undefined.
722 (Currently, 1 << 32 == 1. This behavior may change.)
723
724 Logical operators (!, &&, ||):
725 1. Convert first operand to bool. (true if non-zero, false otherwise)
726 2. If short-circuited, return the result as type bool, value 1 or 0.
727 3. Otherwise, convert second operand to bool, evaluate the result, and return
728 the result in the same fashion.
729
730 Arithmetic comparison operators (< > <= >= == !=):
731 1. Promote operands in the same way as binary arithmetic and bitwise operators.
732 (Integral promotion + Usual arithmetic conversions)
733 2. Return type bool, value 0 or 1 the same way as logical operators.
734
735 Ternary conditional operator (?:):
736 1. Evaluate the conditional and evaluate the operands.
737 2. Return type of expression is the type under usual arithmetic conversions on
738 the second and third operand. (No integral promotions necessary.)
739
740 */
741
742 } // namespace android
743
744