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