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
106 // bitwise negation of a boolean expression always evaluates to 'true'
107 #pragma clang diagnostic push
108 #pragma clang diagnostic ignored "-Wbool-operation"
109 COMPUTE_UNARY(~)
110 #pragma clang diagnostic pop
111
112 // Should not reach here.
113 SHOULD_NOT_REACH() << "Could not handleUnary for " << op << " " << val;
114 return static_cast<T>(0xdeadbeef);
115 }
116
117 template <class T>
handleBinaryCommon(T lval,const std::string & op,T rval)118 T handleBinaryCommon(T lval, const std::string& op, T rval) {
119 COMPUTE_BINARY(+)
120 COMPUTE_BINARY(-)
121 COMPUTE_BINARY(*)
122 COMPUTE_BINARY(/)
123 COMPUTE_BINARY(%)
124 COMPUTE_BINARY(|)
125 COMPUTE_BINARY(^)
126 COMPUTE_BINARY(&)
127 // comparison operators: return 0 or 1 by nature.
128 COMPUTE_BINARY(==)
129 COMPUTE_BINARY(!=)
130 COMPUTE_BINARY(<)
131 COMPUTE_BINARY(>)
132 COMPUTE_BINARY(<=)
133 COMPUTE_BINARY(>=)
134 // Should not reach here.
135 SHOULD_NOT_REACH() << "Could not handleBinaryCommon for "
136 << lval << " " << op << " " << rval;
137 return static_cast<T>(0xdeadbeef);
138 }
139
140 template <class T>
handleShift(T lval,const std::string & op,int64_t rval)141 T handleShift(T lval, const std::string& op, int64_t rval) {
142 // just cast rval to int64_t and it should fit.
143 COMPUTE_BINARY(>>)
144 COMPUTE_BINARY(<<)
145 // Should not reach here.
146 SHOULD_NOT_REACH() << "Could not handleShift for "
147 << lval << " " << op << " " << rval;
148 return static_cast<T>(0xdeadbeef);
149 }
150
handleLogical(bool lval,const std::string & op,bool rval)151 bool handleLogical(bool lval, const std::string& op, bool rval) {
152 COMPUTE_BINARY(||);
153 COMPUTE_BINARY(&&);
154 // Should not reach here.
155 SHOULD_NOT_REACH() << "Could not handleLogical for "
156 << lval << " " << op << " " << rval;
157 return false;
158 }
159
Zero(ScalarType::Kind kind)160 std::unique_ptr<ConstantExpression> ConstantExpression::Zero(ScalarType::Kind kind) {
161 return ValueOf(kind, 0);
162 }
163
One(ScalarType::Kind kind)164 std::unique_ptr<ConstantExpression> ConstantExpression::One(ScalarType::Kind kind) {
165 return ValueOf(kind, 1);
166 }
167
ValueOf(ScalarType::Kind kind,uint64_t value)168 std::unique_ptr<ConstantExpression> ConstantExpression::ValueOf(ScalarType::Kind kind,
169 uint64_t value) {
170 return std::make_unique<LiteralConstantExpression>(kind, value);
171 }
172
ConstantExpression(const std::string & expr)173 ConstantExpression::ConstantExpression(const std::string& expr) : mExpr(expr) {}
174
isEvaluated() const175 bool ConstantExpression::isEvaluated() const {
176 return mIsEvaluated;
177 }
178
LiteralConstantExpression(ScalarType::Kind kind,uint64_t value,const std::string & expr)179 LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value,
180 const std::string& expr)
181 : ConstantExpression(expr) {
182 CHECK(!expr.empty());
183 CHECK(isSupported(kind));
184
185 mTrivialDescription = std::to_string(value) == expr;
186 mValueKind = kind;
187 mValue = value;
188 mIsEvaluated = true;
189 }
190
LiteralConstantExpression(ScalarType::Kind kind,uint64_t value)191 LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value)
192 : LiteralConstantExpression(kind, value, std::to_string(value)) {}
193
tryParse(const std::string & value)194 LiteralConstantExpression* LiteralConstantExpression::tryParse(const std::string& value) {
195 CHECK(!value.empty());
196
197 bool isLong = false, isUnsigned = false;
198 bool isHex = (value[0] == '0' && value.length() > 1 && (value[1] == 'x' || value[1] == 'X'));
199
200 auto rbegin = value.rbegin();
201 auto rend = value.rend();
202 for (; rbegin != rend && (*rbegin == 'u' || *rbegin == 'U' || *rbegin == 'l' || *rbegin == 'L');
203 ++rbegin) {
204 isUnsigned |= (*rbegin == 'u' || *rbegin == 'U');
205 isLong |= (*rbegin == 'l' || *rbegin == 'L');
206 }
207 std::string newVal(value.begin(), rbegin.base());
208 CHECK(!newVal.empty());
209
210 uint64_t rawValue = 0;
211
212 bool parseOK = base::ParseUint(newVal, &rawValue);
213 if (!parseOK) {
214 return nullptr;
215 }
216
217 ScalarType::Kind kind;
218
219 // guess literal type.
220 if(isLong) {
221 if(isUnsigned) // ul
222 kind = SK(UINT64);
223 else // l
224 kind = SK(INT64);
225 } else { // no l suffix
226 if(isUnsigned) { // u
227 if(rawValue <= UINT32_MAX)
228 kind = SK(UINT32);
229 else
230 kind = SK(UINT64);
231 } else { // no suffix
232 if(isHex) {
233 if(rawValue <= INT32_MAX) // rawValue always >= 0
234 kind = SK(INT32);
235 else if(rawValue <= UINT32_MAX)
236 kind = SK(UINT32);
237 else if(rawValue <= INT64_MAX) // rawValue always >= 0
238 kind = SK(INT64);
239 else if(rawValue <= UINT64_MAX)
240 kind = SK(UINT64);
241 else
242 return nullptr;
243 } else {
244 if(rawValue <= INT32_MAX) // rawValue always >= 0
245 kind = SK(INT32);
246 else
247 kind = SK(INT64);
248 }
249 }
250 }
251
252 return new LiteralConstantExpression(kind, rawValue, value);
253 }
254
evaluate()255 void LiteralConstantExpression::evaluate() {
256 // Evaluated in constructor
257 CHECK(isEvaluated());
258 }
259
evaluate()260 void UnaryConstantExpression::evaluate() {
261 if (isEvaluated()) return;
262 CHECK(mUnary->isEvaluated());
263 mIsEvaluated = true;
264
265 mValueKind = mUnary->mValueKind;
266
267 #define CASE_UNARY(__type__) \
268 mValue = handleUnary(mOp, static_cast<__type__>(mUnary->mValue)); \
269 return;
270
271 SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
272 }
273
evaluate()274 void BinaryConstantExpression::evaluate() {
275 if (isEvaluated()) return;
276 CHECK(mLval->isEvaluated());
277 CHECK(mRval->isEvaluated());
278 mIsEvaluated = true;
279
280 bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
281
282 // CASE 1: + - * / % | ^ & < > <= >= == !=
283 if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
284 // promoted kind for both operands.
285 ScalarType::Kind promoted = usualArithmeticConversion(integralPromotion(mLval->mValueKind),
286 integralPromotion(mRval->mValueKind));
287 // result kind.
288 mValueKind = isArithmeticOrBitflip
289 ? promoted // arithmetic or bitflip operators generates promoted type
290 : SK(BOOL); // comparison operators generates bool
291
292 #define CASE_BINARY_COMMON(__type__) \
293 mValue = handleBinaryCommon(static_cast<__type__>(mLval->mValue), mOp, \
294 static_cast<__type__>(mRval->mValue)); \
295 return;
296
297 SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
298 }
299
300 // CASE 2: << >>
301 std::string newOp = mOp;
302 if(OP_IS_BIN_SHIFT) {
303 mValueKind = integralPromotion(mLval->mValueKind);
304 // instead of promoting rval, simply casting it to int64 should also be good.
305 int64_t numBits = mRval->cast<int64_t>();
306 if(numBits < 0) {
307 // shifting with negative number of bits is undefined in C. In HIDL it
308 // is defined as shifting into the other direction.
309 newOp = OPEQ("<<") ? std::string(">>") : std::string("<<");
310 numBits = -numBits;
311 }
312
313 #define CASE_SHIFT(__type__) \
314 mValue = handleShift(static_cast<__type__>(mLval->mValue), newOp, numBits); \
315 return;
316
317 SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
318 }
319
320 // CASE 3: && ||
321 if(OP_IS_BIN_LOGICAL) {
322 mValueKind = SK(BOOL);
323 // easy; everything is bool.
324 mValue = handleLogical(mLval->mValue, mOp, mRval->mValue);
325 return;
326 }
327
328 SHOULD_NOT_REACH();
329 }
330
evaluate()331 void TernaryConstantExpression::evaluate() {
332 if (isEvaluated()) return;
333 CHECK(mCond->isEvaluated());
334 CHECK(mTrueVal->isEvaluated());
335 CHECK(mFalseVal->isEvaluated());
336 mIsEvaluated = true;
337
338 // note: for ?:, unlike arithmetic ops, integral promotion is not processed.
339 mValueKind = usualArithmeticConversion(mTrueVal->mValueKind, mFalseVal->mValueKind);
340
341 #define CASE_TERNARY(__type__) \
342 mValue = mCond->mValue ? (static_cast<__type__>(mTrueVal->mValue)) \
343 : (static_cast<__type__>(mFalseVal->mValue)); \
344 return;
345
346 SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
347 }
348
evaluate()349 void ReferenceConstantExpression::evaluate() {
350 if (isEvaluated()) return;
351 CHECK(mReference->constExpr() != nullptr);
352
353 ConstantExpression* expr = mReference->constExpr();
354 CHECK(expr->isEvaluated());
355
356 mValueKind = expr->mValueKind;
357 mValue = expr->mValue;
358 mIsEvaluated = true;
359 }
360
validate() const361 status_t AttributeConstantExpression::validate() const {
362 if (mTag == "len") {
363 if (!mReference->isEnum()) {
364 std::cerr << "ERROR: " << mExpr << " refers to " << mReference->typeName()
365 << " but should refer to an enum." << std::endl;
366 return UNKNOWN_ERROR;
367 }
368 } else {
369 std::cerr << "ERROR: " << mExpr << " is not a supported tag" << std::endl;
370 return UNKNOWN_ERROR;
371 }
372
373 return OK;
374 }
375
evaluate()376 void AttributeConstantExpression::evaluate() {
377 if (isEvaluated()) return;
378
379 CHECK(mTag == "len");
380 CHECK(mReference->isEnum());
381
382 EnumType* enumType = static_cast<EnumType*>(mReference.get());
383 mValue = enumType->numValueNames();
384
385 if (mValue <= INT32_MAX)
386 mValueKind = SK(INT32);
387 else
388 mValueKind = SK(INT64);
389
390 mIsEvaluated = true;
391 }
392
addOne(ScalarType::Kind baseKind)393 std::unique_ptr<ConstantExpression> ConstantExpression::addOne(ScalarType::Kind baseKind) {
394 auto ret = std::make_unique<BinaryConstantExpression>(
395 this, "+", ConstantExpression::One(baseKind).release());
396 return ret;
397 }
398
value() const399 std::string ConstantExpression::value() const {
400 return value(mValueKind);
401 }
402
value(ScalarType::Kind castKind) const403 std::string ConstantExpression::value(ScalarType::Kind castKind) const {
404 CHECK(isEvaluated());
405 return rawValue(castKind) + descriptionSuffix();
406 }
407
cppValue() const408 std::string ConstantExpression::cppValue() const {
409 return cppValue(mValueKind);
410 }
411
cppValue(ScalarType::Kind castKind) const412 std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
413 CHECK(isEvaluated());
414 std::string literal(rawValue(castKind));
415 // this is a hack to translate
416 // enum x : int64_t { y = 1l << 63 };
417 // into
418 // enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
419 // by adding the explicit cast.
420 // Because 9223372036854775808 is uint64_t, and
421 // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
422 // be narrowed to int64_t.
423 if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
424 literal = "static_cast<" +
425 ScalarType(SK(INT64), nullptr /* parent */).getCppStackType() // "int64_t"
426 + ">(" + literal + "ull)";
427 } else {
428 // add suffix if necessary.
429 if (castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
430 if (castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
431 }
432
433 return literal + descriptionSuffix();
434 }
435
javaValue() const436 std::string ConstantExpression::javaValue() const {
437 return javaValue(mValueKind);
438 }
439
javaValue(ScalarType::Kind castKind) const440 std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
441 CHECK(isEvaluated());
442 std::string literal;
443
444 switch(castKind) {
445 case SK(UINT64):
446 literal = rawValue(SK(INT64)) + "L";
447 break;
448 case SK(INT64):
449 literal = rawValue(SK(INT64)) + "L";
450 break;
451 case SK(UINT32):
452 literal = rawValue(SK(INT32));
453 break;
454 case SK(UINT16):
455 literal = rawValue(SK(INT16));
456 break;
457 case SK(UINT8):
458 literal = rawValue(SK(INT8));
459 break;
460 case SK(BOOL) :
461 literal = this->cast<bool>() ? "true" : "false";
462 break;
463 default:
464 literal = rawValue(castKind);
465 break;
466 }
467
468 return literal + descriptionSuffix();
469 }
470
expression() const471 const std::string& ConstantExpression::expression() const {
472 return mExpr;
473 }
474
rawValue() const475 std::string ConstantExpression::rawValue() const {
476 return rawValue(mValueKind);
477 }
478
rawValue(ScalarType::Kind castKind) const479 std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
480 CHECK(isEvaluated());
481
482 #define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
483
484 SWITCH_KIND(castKind, CASE_STR, SHOULD_NOT_REACH(); return nullptr; );
485 }
486
487 template<typename T>
cast() const488 T ConstantExpression::cast() const {
489 CHECK(isEvaluated());
490
491 #define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
492
493 SWITCH_KIND(mValueKind, CASE_CAST_T, SHOULD_NOT_REACH(); return 0; );
494 }
495
descriptionSuffix() const496 std::string ConstantExpression::descriptionSuffix() const {
497 CHECK(isEvaluated());
498
499 if (!mTrivialDescription) {
500 CHECK(!mExpr.empty());
501
502 return " /* " + mExpr + " */";
503 }
504 return "";
505 }
506
castSizeT() const507 size_t ConstantExpression::castSizeT() const {
508 CHECK(isEvaluated());
509 return this->cast<size_t>();
510 }
511
isReferenceConstantExpression() const512 bool ConstantExpression::isReferenceConstantExpression() const {
513 return false;
514 }
515
validate() const516 status_t ConstantExpression::validate() const {
517 return OK;
518 }
519
getConstantExpressions()520 std::vector<ConstantExpression*> ConstantExpression::getConstantExpressions() {
521 const auto& constRet = static_cast<const ConstantExpression*>(this)->getConstantExpressions();
522 std::vector<ConstantExpression*> ret(constRet.size());
523 std::transform(constRet.begin(), constRet.end(), ret.begin(),
524 [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
525 return ret;
526 }
527
getReferences()528 std::vector<Reference<LocalIdentifier>*> ConstantExpression::getReferences() {
529 const auto& constRet = static_cast<const ConstantExpression*>(this)->getReferences();
530 std::vector<Reference<LocalIdentifier>*> ret(constRet.size());
531 std::transform(constRet.begin(), constRet.end(), ret.begin(),
532 [](const auto* ce) { return const_cast<Reference<LocalIdentifier>*>(ce); });
533 return ret;
534 }
535
getReferences() const536 std::vector<const Reference<LocalIdentifier>*> ConstantExpression::getReferences() const {
537 return {};
538 }
539
getTypeReferences()540 std::vector<Reference<Type>*> ConstantExpression::getTypeReferences() {
541 const auto& constRet = static_cast<const ConstantExpression*>(this)->getTypeReferences();
542 std::vector<Reference<Type>*> ret(constRet.size());
543 std::transform(constRet.begin(), constRet.end(), ret.begin(),
544 [](const auto* ce) { return const_cast<Reference<Type>*>(ce); });
545 return ret;
546 }
547
getTypeReferences() const548 std::vector<const Reference<Type>*> ConstantExpression::getTypeReferences() const {
549 return {};
550 }
551
recursivePass(const std::function<status_t (ConstantExpression *)> & func,std::unordered_set<const ConstantExpression * > * visited,bool processBeforeDependencies)552 status_t ConstantExpression::recursivePass(const std::function<status_t(ConstantExpression*)>& func,
553 std::unordered_set<const ConstantExpression*>* visited,
554 bool processBeforeDependencies) {
555 if (mIsPostParseCompleted) return OK;
556
557 if (visited->find(this) != visited->end()) return OK;
558 visited->insert(this);
559
560 if (processBeforeDependencies) {
561 status_t err = func(this);
562 if (err != OK) return err;
563 }
564
565 for (auto* nextCE : getConstantExpressions()) {
566 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
567 if (err != OK) return err;
568 }
569
570 for (auto* nextRef : getReferences()) {
571 auto* nextCE = nextRef->shallowGet()->constExpr();
572 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
573 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
574 if (err != OK) return err;
575 }
576
577 if (!processBeforeDependencies) {
578 status_t err = func(this);
579 if (err != OK) return err;
580 }
581
582 return OK;
583 }
584
recursivePass(const std::function<status_t (const ConstantExpression *)> & func,std::unordered_set<const ConstantExpression * > * visited,bool processBeforeDependencies) const585 status_t ConstantExpression::recursivePass(
586 const std::function<status_t(const ConstantExpression*)>& func,
587 std::unordered_set<const ConstantExpression*>* visited, bool processBeforeDependencies) const {
588 if (mIsPostParseCompleted) return OK;
589
590 if (visited->find(this) != visited->end()) return OK;
591 visited->insert(this);
592
593 if (processBeforeDependencies) {
594 status_t err = func(this);
595 if (err != OK) return err;
596 }
597
598 for (const auto* nextCE : getConstantExpressions()) {
599 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
600 if (err != OK) return err;
601 }
602
603 for (const auto* nextRef : getReferences()) {
604 const auto* nextCE = nextRef->shallowGet()->constExpr();
605 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
606 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
607 if (err != OK) return err;
608 }
609
610 if (!processBeforeDependencies) {
611 status_t err = func(this);
612 if (err != OK) return err;
613 }
614
615 return OK;
616 }
617
CheckAcyclicStatus(status_t status,const ConstantExpression * cycleEnd,const ReferenceConstantExpression * lastReference)618 ConstantExpression::CheckAcyclicStatus::CheckAcyclicStatus(
619 status_t status, const ConstantExpression* cycleEnd,
620 const ReferenceConstantExpression* lastReference)
621 : status(status), cycleEnd(cycleEnd), lastReference(lastReference) {
622 CHECK(cycleEnd == nullptr || status != OK);
623 CHECK((cycleEnd == nullptr) == (lastReference == nullptr));
624 }
625
checkAcyclic(std::unordered_set<const ConstantExpression * > * visited,std::unordered_set<const ConstantExpression * > * stack) const626 ConstantExpression::CheckAcyclicStatus ConstantExpression::checkAcyclic(
627 std::unordered_set<const ConstantExpression*>* visited,
628 std::unordered_set<const ConstantExpression*>* stack) const {
629 if (stack->find(this) != stack->end()) {
630 CHECK(isReferenceConstantExpression())
631 << "Only reference constant expression could be the cycle end";
632
633 std::cerr << "ERROR: Cyclic declaration:\n";
634 return CheckAcyclicStatus(UNKNOWN_ERROR, this,
635 static_cast<const ReferenceConstantExpression*>(this));
636 }
637
638 if (visited->find(this) != visited->end()) return CheckAcyclicStatus(OK);
639 visited->insert(this);
640 stack->insert(this);
641
642 for (const auto* nextCE : getConstantExpressions()) {
643 auto err = nextCE->checkAcyclic(visited, stack);
644 if (err.status != OK) {
645 return err;
646 }
647 }
648
649 for (const auto* nextRef : getReferences()) {
650 const auto* nextCE = nextRef->shallowGet()->constExpr();
651 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
652 auto err = nextCE->checkAcyclic(visited, stack);
653
654 if (err.status != OK) {
655 if (err.cycleEnd == nullptr) return err;
656
657 // Only ReferenceConstantExpression has references,
658 CHECK(isReferenceConstantExpression())
659 << "Only reference constant expression could have refereneces";
660
661 // mExpr is defined explicitly before evaluation
662 std::cerr << " '" << err.lastReference->mExpr << "' in '" << mExpr << "' at "
663 << nextRef->location() << "\n";
664
665 if (err.cycleEnd == this) {
666 return CheckAcyclicStatus(err.status);
667 }
668 return CheckAcyclicStatus(err.status, err.cycleEnd,
669 static_cast<const ReferenceConstantExpression*>(this));
670 }
671 }
672
673 CHECK(stack->find(this) != stack->end());
674 stack->erase(this);
675 return CheckAcyclicStatus(OK);
676 }
677
setPostParseCompleted()678 void ConstantExpression::setPostParseCompleted() {
679 CHECK(!mIsPostParseCompleted);
680 mIsPostParseCompleted = true;
681 }
682
surroundWithParens()683 void ConstantExpression::surroundWithParens() {
684 mExpr = "(" + mExpr + ")";
685 }
686
getConstantExpressions() const687 std::vector<const ConstantExpression*> LiteralConstantExpression::getConstantExpressions() const {
688 return {};
689 }
690
UnaryConstantExpression(const std::string & op,ConstantExpression * value)691 UnaryConstantExpression::UnaryConstantExpression(const std::string& op, ConstantExpression* value)
692 : ConstantExpression(op + value->mExpr), mUnary(value), mOp(op) {}
693
getConstantExpressions() const694 std::vector<const ConstantExpression*> UnaryConstantExpression::getConstantExpressions() const {
695 return {mUnary};
696 }
697
BinaryConstantExpression(ConstantExpression * lval,const std::string & op,ConstantExpression * rval)698 BinaryConstantExpression::BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
699 ConstantExpression* rval)
700 : ConstantExpression(lval->mExpr + " " + op + " " + rval->mExpr),
701 mLval(lval),
702 mRval(rval),
703 mOp(op) {}
704
getConstantExpressions() const705 std::vector<const ConstantExpression*> BinaryConstantExpression::getConstantExpressions() const {
706 return {mLval, mRval};
707 }
708
TernaryConstantExpression(ConstantExpression * cond,ConstantExpression * trueVal,ConstantExpression * falseVal)709 TernaryConstantExpression::TernaryConstantExpression(ConstantExpression* cond,
710 ConstantExpression* trueVal,
711 ConstantExpression* falseVal)
712 : ConstantExpression(cond->mExpr + "?" + trueVal->mExpr + ":" + falseVal->mExpr),
713 mCond(cond),
714 mTrueVal(trueVal),
715 mFalseVal(falseVal) {}
716
getConstantExpressions() const717 std::vector<const ConstantExpression*> TernaryConstantExpression::getConstantExpressions() const {
718 return {mCond, mTrueVal, mFalseVal};
719 }
720
ReferenceConstantExpression(const Reference<LocalIdentifier> & value,const std::string & expr)721 ReferenceConstantExpression::ReferenceConstantExpression(const Reference<LocalIdentifier>& value,
722 const std::string& expr)
723 : ConstantExpression(expr), mReference(value) {
724 mTrivialDescription = mExpr.empty();
725 }
726
isReferenceConstantExpression() const727 bool ReferenceConstantExpression::isReferenceConstantExpression() const {
728 return true;
729 }
730
getConstantExpressions() const731 std::vector<const ConstantExpression*> ReferenceConstantExpression::getConstantExpressions() const {
732 // Returns reference instead
733 return {};
734 }
735
getReferences() const736 std::vector<const Reference<LocalIdentifier>*> ReferenceConstantExpression::getReferences() const {
737 return {&mReference};
738 }
739
AttributeConstantExpression(const Reference<Type> & value,const std::string & fqname,const std::string & tag)740 AttributeConstantExpression::AttributeConstantExpression(const Reference<Type>& value,
741 const std::string& fqname,
742 const std::string& tag)
743 : ConstantExpression(fqname + "#" + tag), mReference(value), mTag(tag) {}
744
getConstantExpressions() const745 std::vector<const ConstantExpression*> AttributeConstantExpression::getConstantExpressions() const {
746 // Returns reference instead
747 return {};
748 }
749
getTypeReferences() const750 std::vector<const Reference<Type>*> AttributeConstantExpression::getTypeReferences() const {
751 return {&mReference};
752 }
753
754 /*
755
756 Evaluating expressions in HIDL language
757
758 The following rules are mostly like that in:
759 http://en.cppreference.com/w/cpp/language/operator_arithmetic
760 http://en.cppreference.com/w/cpp/language/operator_logical
761 http://en.cppreference.com/w/cpp/language/operator_comparison
762 http://en.cppreference.com/w/cpp/language/operator_other
763
764 The type of literal is the first type which the value
765 can fit from the list of types depending on the suffix and bases.
766
767 suffix decimal bases hexadecimal bases
768 no suffix int32_t int32_t
769 int64_t uint32_t
770 int64_t
771 uint64_t
772
773 u/U uint32_t (same as left)
774 uint64_t
775
776 l/L int64_t int64_t
777
778 ul/UL/uL/Ul uint64_t uint64_t
779
780
781 Note: There are no negative integer literals.
782 -1 is the unary minus applied to 1.
783
784 Unary arithmetic and bitwise operators (~ + -):
785 don't change the type of the argument.
786 (so -1u = -(1u) has type uint32_t)
787
788 Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
789 1. Integral promotion is first applied on both sides.
790 2. If both operands have the same type, no promotion is necessary.
791 3. Usual arithmetic conversions.
792
793 Integral promotion: if an operand is of a type with less than 32 bits,
794 (including bool), it is promoted to int32_t.
795
796 Usual arithmetic conversions:
797 1. If operands are both signed or both unsigned, lesser conversion rank is
798 converted to greater conversion rank.
799 2. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
800 3. Otherwise, if signed's type can hold all values in unsigned's type,
801 -> signed's type
802 4. Otherwise, both converted to the unsigned counterpart of the signed operand's
803 type.
804 rank: bool < int8_t < int16_t < int32_t < int64_t
805
806
807 Shift operators (<< >>):
808 1. Integral promotion is applied on both sides.
809 2. For unsigned a, a << b discards bits that shifts out.
810 For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
811 For signed negative a, a << b gives error.
812 3. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
813 For signed negative a, a >> b discards bits that shifts out, and the signed
814 bit gets extended. ("arithmetic right shift")
815 4. Shifting with negative number of bits is undefined. (Currently, the
816 parser will shift into the other direction. This behavior may change.)
817 5. Shifting with number of bits exceeding the width of the type is undefined.
818 (Currently, 1 << 32 == 1. This behavior may change.)
819
820 Logical operators (!, &&, ||):
821 1. Convert first operand to bool. (true if non-zero, false otherwise)
822 2. If short-circuited, return the result as type bool, value 1 or 0.
823 3. Otherwise, convert second operand to bool, evaluate the result, and return
824 the result in the same fashion.
825
826 Arithmetic comparison operators (< > <= >= == !=):
827 1. Promote operands in the same way as binary arithmetic and bitwise operators.
828 (Integral promotion + Usual arithmetic conversions)
829 2. Return type bool, value 0 or 1 the same way as logical operators.
830
831 Ternary conditional operator (?:):
832 1. Evaluate the conditional and evaluate the operands.
833 2. Return type of expression is the type under usual arithmetic conversions on
834 the second and third operand. (No integral promotions necessary.)
835
836 */
837
838 } // namespace android
839
840