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