• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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