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