• 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 
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