Merge "ABI stable smaller HIDL libs"
diff --git a/ConstantExpression.cpp b/ConstantExpression.cpp
index fe0ff4c..eba28e1 100644
--- a/ConstantExpression.cpp
+++ b/ConstantExpression.cpp
@@ -23,12 +23,12 @@
 #include <sstream>
 
 #include "EnumType.h"
-#include "Scope.h"  // LocalIdentifier
 
 // The macros are really nasty here. Consider removing
 // as many macros as possible.
 
-#define OPEQ(__y__) (std::string(op) == std::string(__y__))
+#define STREQ(__x__, __y__) (strcmp((__x__), (__y__)) == 0)
+#define OPEQ(__y__) STREQ(op, __y__)
 #define COMPUTE_UNARY(__op__)  if(OPEQ(#__op__)) return __op__ val;
 #define COMPUTE_BINARY(__op__) if(OPEQ(#__op__)) return lval __op__ rval;
 #define OP_IS_BIN_ARITHMETIC  (OPEQ("+") || OPEQ("-") || OPEQ("*") || OPEQ("/") || OPEQ("%"))
@@ -96,7 +96,7 @@
 }
 
 template <class T>
-T handleUnary(const std::string& op, T val) {
+T handleUnary(const char *op, T val) {
     COMPUTE_UNARY(+)
     COMPUTE_UNARY(-)
     COMPUTE_UNARY(!)
@@ -107,7 +107,7 @@
 }
 
 template <class T>
-T handleBinaryCommon(T lval, const std::string& op, T rval) {
+T handleBinaryCommon(T lval, const char *op, T rval) {
     COMPUTE_BINARY(+)
     COMPUTE_BINARY(-)
     COMPUTE_BINARY(*)
@@ -130,7 +130,7 @@
 }
 
 template <class T>
-T handleShift(T lval, const std::string& op, int64_t rval) {
+T handleShift(T lval, const char *op, int64_t rval) {
     // just cast rval to int64_t and it should fit.
     COMPUTE_BINARY(>>)
     COMPUTE_BINARY(<<)
@@ -140,7 +140,7 @@
     return static_cast<T>(0xdeadbeef);
 }
 
-bool handleLogical(bool lval, const std::string& op, bool rval) {
+bool handleLogical(bool lval, const char *op, bool rval) {
     COMPUTE_BINARY(||);
     COMPUTE_BINARY(&&);
     // Should not reach here.
@@ -149,51 +149,66 @@
     return false;
 }
 
-std::unique_ptr<ConstantExpression> ConstantExpression::Zero(ScalarType::Kind kind) {
-    return ValueOf(kind, 0);
+ConstantExpression::ConstantExpression() {
 }
 
-std::unique_ptr<ConstantExpression> ConstantExpression::One(ScalarType::Kind kind) {
-    return ValueOf(kind, 1);
+ConstantExpression ConstantExpression::Zero(ScalarType::Kind kind) {
+    ConstantExpression ce = ValueOf(kind, 0);
+    ce.mExpr = "0";
+    return ce;
 }
 
-std::unique_ptr<ConstantExpression> ConstantExpression::ValueOf(ScalarType::Kind kind,
-                                                                uint64_t value) {
-    return std::make_unique<LiteralConstantExpression>(kind, value);
+ConstantExpression ConstantExpression::One(ScalarType::Kind kind) {
+    ConstantExpression ce = ValueOf(kind, 1);
+    ce.mExpr = "1";
+    return ce;
 }
 
-bool ConstantExpression::isEvaluated() const {
-    return mIsEvaluated;
-}
-
-LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value) {
+ConstantExpression ConstantExpression::ValueOf(ScalarType::Kind kind, uint64_t value) {
+    ConstantExpression ce;
     CHECK(isSupported(kind));
-    mTrivialDescription = true;
-    mExpr = std::to_string(value);
-    mValueKind = kind;
-    mValue = value;
-    mIsEvaluated = true;
+
+    ce.mExpr = "";
+    ce.mType = kConstExprLiteral;
+    ce.mValueKind = kind;
+    ce.mValue = value;
+    ce.mTrivialDescription = true;
+    return ce;
+}
+ConstantExpression::ConstantExpression(const ConstantExpression& other) {
+    *this = other;
 }
 
-LiteralConstantExpression::LiteralConstantExpression(const std::string& value) {
-    CHECK(!value.empty());
-    mIsEvaluated = true;
-    mTrivialDescription = true;
-    mExpr = value;
+/* Copy constructor, with the expr overriden and treated non-trivial */
+ConstantExpression::ConstantExpression(const ConstantExpression& other, std::string expr) {
+    *this = other;
+    mExpr = expr;
+    mTrivialDescription = false;
+}
 
+ConstantExpression& ConstantExpression::operator=(const ConstantExpression& other) {
+    mType = other.mType;
+    mValueKind = other.mValueKind;
+    mValue = other.mValue;
+    mExpr = other.mExpr;
+    mTrivialDescription = other.mTrivialDescription;
+    return *this;
+}
+
+/* Literals. */
+ConstantExpression::ConstantExpression(const char *value)
+        : mExpr(value), mType(kConstExprLiteral), mTrivialDescription(true) {
+    const char* head = value, *tail = head + strlen(value) - 1;
     bool isLong = false, isUnsigned = false;
-    bool isHex = (value[0] == '0' && value.length() > 1 && (value[1] == 'x' || value[1] == 'X'));
-
-    auto rbegin = value.rbegin();
-    auto rend = value.rend();
-    for (; rbegin != rend && (*rbegin == 'u' || *rbegin == 'U' || *rbegin == 'l' || *rbegin == 'L');
-         ++rbegin) {
-        isUnsigned |= (*rbegin == 'u' || *rbegin == 'U');
-        isLong |= (*rbegin == 'l' || *rbegin == 'L');
+    bool isHex = (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'));
+    while(tail >= head && (*tail == 'u' || *tail == 'U' || *tail == 'l' || *tail == 'L')) {
+        isUnsigned |= (*tail == 'u' || *tail == 'U');
+        isLong     |= (*tail == 'l' || *tail == 'L');
+        tail--;
     }
-    std::string newVal(value.begin(), rbegin.base());
-    CHECK(!newVal.empty());
+    char *newVal = strndup(value, tail - head + 1);
     bool parseOK = base::ParseUint(newVal, &mValue);
+    free(newVal);
     CHECK(parseOK) << "Could not parse as integer: " << value;
 
     // guess literal type.
@@ -228,56 +243,47 @@
     }
 }
 
-void LiteralConstantExpression::evaluate() {
-    // Evaluated in constructor
-    CHECK(isEvaluated());
-}
+/* Unary operations. */
+ConstantExpression::ConstantExpression(const char *op,
+                                       const ConstantExpression *value)
+        : mExpr(std::string("(") + op + value->mExpr + ")"),
+          mType(kConstExprUnary),
+          mValueKind(value->mValueKind) {
 
-void UnaryConstantExpression::evaluate() {
-    if (isEvaluated()) return;
-    value->evaluate();
-    mIsEvaluated = true;
-
-    mExpr = std::string("(") + op + value->description() + ")";
-    mValueKind = value->mValueKind;
-
-#define CASE_UNARY(__type__)                                        \
-    mValue = handleUnary(op, static_cast<__type__>(value->mValue)); \
-    return;
+#define CASE_UNARY(__type__)\
+            mValue = handleUnary(op, static_cast<__type__>(value->mValue)); return;
 
     SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
 }
 
-void BinaryConstantExpression::evaluate() {
-    if (isEvaluated()) return;
-    lval->evaluate();
-    rval->evaluate();
-    mIsEvaluated = true;
-
-    mExpr = std::string("(") + lval->description() + " " + op + " " + rval->description() + ")";
+/* Binary operations. */
+ConstantExpression::ConstantExpression(const ConstantExpression *lval,
+                                       const char *op,
+                                       const ConstantExpression* rval)
+        : mExpr(std::string("(") + lval->mExpr + " " + op + " " + rval->mExpr + ")"),
+          mType(kConstExprBinary)
+{
 
     bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
 
     // CASE 1: + - *  / % | ^ & < > <= >= == !=
     if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
         // promoted kind for both operands.
-        ScalarType::Kind promoted = usualArithmeticConversion(integralPromotion(lval->mValueKind),
-                                                              integralPromotion(rval->mValueKind));
+        ScalarType::Kind promoted = usualArithmeticConversion(
+                integralPromotion(lval->mValueKind),
+                integralPromotion(rval->mValueKind));
         // result kind.
         mValueKind = isArithmeticOrBitflip
                     ? promoted // arithmetic or bitflip operators generates promoted type
                     : SK(BOOL); // comparison operators generates bool
 
-#define CASE_BINARY_COMMON(__type__)                                     \
-    mValue = handleBinaryCommon(static_cast<__type__>(lval->mValue), op, \
-                                static_cast<__type__>(rval->mValue));    \
-    return;
+#define CASE_BINARY_COMMON(__type__)\
+            mValue = handleBinaryCommon(static_cast<__type__>(lval->mValue), op, static_cast<__type__>(rval->mValue)); return;
 
         SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
     }
 
     // CASE 2: << >>
-    std::string newOp = op;
     if(OP_IS_BIN_SHIFT) {
         mValueKind = integralPromotion(lval->mValueKind);
         // instead of promoting rval, simply casting it to int64 should also be good.
@@ -285,13 +291,12 @@
         if(numBits < 0) {
             // shifting with negative number of bits is undefined in C. In HIDL it
             // is defined as shifting into the other direction.
-            newOp = OPEQ("<<") ? std::string(">>") : std::string("<<");
+            op = OPEQ("<<") ? ">>" : "<<";
             numBits = -numBits;
         }
 
-#define CASE_SHIFT(__type__)                                                   \
-    mValue = handleShift(static_cast<__type__>(lval->mValue), newOp, numBits); \
-    return;
+#define CASE_SHIFT(__type__)\
+            mValue = handleShift(static_cast<__type__>(lval->mValue), op, numBits); return;
 
         SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
     }
@@ -307,73 +312,56 @@
     SHOULD_NOT_REACH();
 }
 
-void TernaryConstantExpression::evaluate() {
-    if (isEvaluated()) return;
-    cond->evaluate();
-    trueVal->evaluate();
-    falseVal->evaluate();
-    mIsEvaluated = true;
-
-    mExpr = std::string("(") + cond->description() + "?" + trueVal->description() + ":" +
-            falseVal->description() + ")";
+/* Ternary ?: operation. */
+ConstantExpression::ConstantExpression(const ConstantExpression *cond,
+                                       const ConstantExpression *trueVal,
+                                       const ConstantExpression *falseVal)
+        : mExpr(std::string("(") + cond->mExpr + "?" + trueVal->mExpr
+                + ":" + falseVal->mExpr + ")"),
+          mType(kConstExprTernary) {
 
     // note: for ?:, unlike arithmetic ops, integral promotion is not necessary.
-    mValueKind = usualArithmeticConversion(trueVal->mValueKind, falseVal->mValueKind);
+    mValueKind = usualArithmeticConversion(trueVal->mValueKind,
+                                           falseVal->mValueKind);
 
-#define CASE_TERNARY(__type__)                                         \
-    mValue = cond->mValue ? (static_cast<__type__>(trueVal->mValue))   \
-                          : (static_cast<__type__>(falseVal->mValue)); \
-    return;
+#define CASE_TERNARY(__type__)\
+        mValue = cond->mValue ? (static_cast<__type__>(trueVal->mValue)) : (static_cast<__type__>(falseVal->mValue)); return;
 
     SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
 }
 
-void ReferenceConstantExpression::evaluate() {
-    if (isEvaluated()) return;
-
-    ConstantExpression* expr = value->constExpr();
-    CHECK(expr != nullptr);
-    expr->evaluate();
-
-    mValueKind = expr->mValueKind;
-    mValue = expr->mValue;
-    mIsEvaluated = true;
+ConstantExpression ConstantExpression::addOne() const {
+    ConstantExpression myOne = ConstantExpression::One(mValueKind);
+    return ConstantExpression(this, "+", &myOne).toLiteral();
 }
 
-std::unique_ptr<ConstantExpression> ConstantExpression::addOne(ScalarType::Kind baseKind) {
-    auto ret = std::make_unique<BinaryConstantExpression>(
-        this, "+", ConstantExpression::One(baseKind).release());
-    ret->mTrivialDescription = true;
-    return ret;
+ConstantExpression &ConstantExpression::toLiteral() {
+    mExpr = value();
+    mType = kConstExprLiteral;
+    return *this;
 }
 
-const std::string& ConstantExpression::description() const {
-    CHECK(isEvaluated());
+const std::string &ConstantExpression::description() const {
     return mExpr;
 }
 
 bool ConstantExpression::descriptionIsTrivial() const {
-    CHECK(isEvaluated());
     return mTrivialDescription;
 }
 
 std::string ConstantExpression::value() const {
-    CHECK(isEvaluated());
     return rawValue(mValueKind);
 }
 
 std::string ConstantExpression::value(ScalarType::Kind castKind) const {
-    CHECK(isEvaluated());
     return rawValue(castKind);
 }
 
 std::string ConstantExpression::cppValue() const {
-    CHECK(isEvaluated());
     return cppValue(mValueKind);
 }
 
 std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
-    CHECK(isEvaluated());
     std::string literal(rawValue(castKind));
     // this is a hack to translate
     //       enum x : int64_t {  y = 1l << 63 };
@@ -396,12 +384,10 @@
 }
 
 std::string ConstantExpression::javaValue() const {
-    CHECK(isEvaluated());
     return javaValue(mValueKind);
 }
 
 std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
-    CHECK(isEvaluated());
     switch(castKind) {
         case SK(UINT64): return rawValue(SK(INT64)) + "L";
         case SK(INT64):  return rawValue(SK(INT64)) + "L";
@@ -416,7 +402,6 @@
 }
 
 std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
-    CHECK(isEvaluated());
 
 #define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
 
@@ -425,7 +410,6 @@
 
 template<typename T>
 T ConstantExpression::cast() const {
-    CHECK(isEvaluated());
 
 #define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
 
@@ -433,28 +417,9 @@
 }
 
 size_t ConstantExpression::castSizeT() const {
-    CHECK(isEvaluated());
     return this->cast<size_t>();
 }
 
-UnaryConstantExpression::UnaryConstantExpression(const std::string& op, ConstantExpression* value)
-    : value(value), op(op) {}
-
-BinaryConstantExpression::BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
-                                                   ConstantExpression* rval)
-    : lval(lval), rval(rval), op(op) {}
-
-TernaryConstantExpression::TernaryConstantExpression(ConstantExpression* cond,
-                                                     ConstantExpression* trueVal,
-                                                     ConstantExpression* falseVal)
-    : cond(cond), trueVal(trueVal), falseVal(falseVal) {}
-
-ReferenceConstantExpression::ReferenceConstantExpression(const Reference<LocalIdentifier>& value,
-                                                         const std::string& expr)
-    : value(value) {
-    mExpr = expr;
-}
-
 /*
 
 Evaluating expressions in HIDL language
diff --git a/ConstantExpression.h b/ConstantExpression.h
index 0b44af7..2c955d4 100644
--- a/ConstantExpression.h
+++ b/ConstantExpression.h
@@ -19,39 +19,45 @@
 #define CONSTANT_EXPRESSION_H_
 
 #include <android-base/macros.h>
-#include <memory>
 #include <string>
-
-#include "Reference.h"
 #include "ScalarType.h"
 
 namespace android {
 
-struct LocalIdentifier;
-
-struct LiteralConstantExpression;
-struct UnaryConstantExpression;
-struct BinaryConstantExpression;
-struct TernaryConstantExpression;
-struct ReferenceConstantExpression;
-
 /**
  * A constant expression is represented by a tree.
  */
 struct ConstantExpression {
-    static std::unique_ptr<ConstantExpression> Zero(ScalarType::Kind kind);
-    static std::unique_ptr<ConstantExpression> One(ScalarType::Kind kind);
-    static std::unique_ptr<ConstantExpression> ValueOf(ScalarType::Kind kind, uint64_t value);
 
-    /*
-     * Runs recursive evaluation.
-     * Provides sort of lazy computation,
-     * mainly used for forward identifier reference.
-     */
-    virtual void evaluate() = 0;
+    enum ConstExprType {
+        kConstExprLiteral,
+        kConstExprUnary,
+        kConstExprBinary,
+        kConstExprTernary
+    };
 
-    /* Returns true iff the value has already been evaluated. */
-    bool isEvaluated() const;
+    /* Default constructor. */
+    ConstantExpression();
+    /* Copy constructor. */
+    ConstantExpression(const ConstantExpression& other);
+    /* Copy constructor, with the expr overriden. */
+    ConstantExpression(const ConstantExpression& other, std::string expr);
+    /* Literals */
+    ConstantExpression(const char *value);
+    /* binary operations */
+    ConstantExpression(const ConstantExpression *value1,
+        const char *op, const ConstantExpression* value2);
+    /* unary operations */
+    ConstantExpression(const char *op, const ConstantExpression *value);
+    /* ternary ?: */
+    ConstantExpression(const ConstantExpression *cond,
+                       const ConstantExpression *trueVal,
+                       const ConstantExpression *falseVal);
+
+    static ConstantExpression Zero(ScalarType::Kind kind);
+    static ConstantExpression One(ScalarType::Kind kind);
+    static ConstantExpression ValueOf(ScalarType::Kind kind, uint64_t value);
+
     /* Evaluated result in a string form. */
     std::string value() const;
     /* Evaluated result in a string form. */
@@ -64,21 +70,22 @@
     std::string cppValue(ScalarType::Kind castKind) const;
     /* Evaluated result in a string form, with given contextual kind. */
     std::string javaValue(ScalarType::Kind castKind) const;
-    /* Formatted expression with type. */
-    const std::string& description() const;
+    /* Original expression with type. */
+    const std::string &description() const;
     /* See mTrivialDescription */
     bool descriptionIsTrivial() const;
     /* Return a ConstantExpression that is 1 plus the original. */
-    std::unique_ptr<ConstantExpression> addOne(ScalarType::Kind baseKind);
+    ConstantExpression addOne() const;
+    /* Assignment operator. */
+    ConstantExpression& operator=(const ConstantExpression& other);
 
     size_t castSizeT() const;
 
-   private:
-    /* If the result value has been evaluated. */
-    bool mIsEvaluated = false;
-
+private:
     /* The formatted expression. */
     std::string mExpr;
+    /* The type of the expression. Hints on its original form. */
+    ConstExprType mType;
     /* The kind of the result value. */
     ScalarType::Kind mValueKind;
     /* The stored result value. */
@@ -92,65 +99,15 @@
      * digits) converted from mValue.
      */
     std::string rawValue(ScalarType::Kind castKind) const;
+    /* Trim unnecessary information. Only mValue and mValueKind is kept. */
+    ConstantExpression &toLiteral();
 
     /*
      * Return the value casted to the given type.
      * First cast it according to mValueKind, then cast it to T.
      * Assumes !containsIdentifiers()
      */
-    template <typename T>
-    T cast() const;
-
-    friend struct LiteralConstantExpression;
-    friend struct UnaryConstantExpression;
-    friend struct BinaryConstantExpression;
-    friend struct TernaryConstantExpression;
-    friend struct ReferenceConstantExpression;
-};
-
-struct LiteralConstantExpression : public ConstantExpression {
-    LiteralConstantExpression(ScalarType::Kind kind, uint64_t value);
-    LiteralConstantExpression(const std::string& value);
-    void evaluate() override;
-};
-
-struct UnaryConstantExpression : public ConstantExpression {
-    UnaryConstantExpression(const std::string& op, ConstantExpression* value);
-    void evaluate() override;
-
-   private:
-    ConstantExpression* const value;
-    std::string op;
-};
-
-struct BinaryConstantExpression : public ConstantExpression {
-    BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
-                             ConstantExpression* rval);
-    void evaluate() override;
-
-   private:
-    ConstantExpression* const lval;
-    ConstantExpression* const rval;
-    const std::string op;
-};
-
-struct TernaryConstantExpression : public ConstantExpression {
-    TernaryConstantExpression(ConstantExpression* cond, ConstantExpression* trueVal,
-                              ConstantExpression* falseVal);
-    void evaluate() override;
-
-   private:
-    ConstantExpression* const cond;
-    ConstantExpression* const trueVal;
-    ConstantExpression* const falseVal;
-};
-
-struct ReferenceConstantExpression : public ConstantExpression {
-    ReferenceConstantExpression(const Reference<LocalIdentifier>& value, const std::string& expr);
-    void evaluate() override;
-
-   private:
-    Reference<LocalIdentifier> value;
+    template <typename T> T cast() const;
 };
 
 }  // namespace android
diff --git a/EnumType.cpp b/EnumType.cpp
index 02c6c69..9f70287 100644
--- a/EnumType.cpp
+++ b/EnumType.cpp
@@ -692,16 +692,18 @@
     return mValue;
 }
 
-void EnumValue::autofill(const EnumValue* prev, const ScalarType* type) {
-    if (mValue != nullptr) return;
+void EnumValue::autofill(const EnumValue *prev, const ScalarType *type) {
+    if(mValue != nullptr)
+        return;
     mIsAutoFill = true;
-    if (prev == nullptr) {
-        mValue = ConstantExpression::Zero(type->getKind()).release();
+    ConstantExpression *value = new ConstantExpression();
+    if(prev == nullptr) {
+        *value = ConstantExpression::Zero(type->getKind());
     } else {
         CHECK(prev->mValue != nullptr);
-        mValue = prev->mValue->addOne(type->getKind()).release();
+        *value = prev->mValue->addOne();
     }
-    mValue->evaluate();
+    mValue = value;
 }
 
 bool EnumValue::isAutoFill() const {
diff --git a/EnumType.h b/EnumType.h
index 95a6174..35db597 100644
--- a/EnumType.h
+++ b/EnumType.h
@@ -131,14 +131,14 @@
     std::string javaValue(ScalarType::Kind castKind) const;
     std::string comment() const;
     void autofill(const EnumValue *prev, const ScalarType *type);
-    ConstantExpression* constExpr() const override;
+    ConstantExpression *constExpr() const;
 
     bool isAutoFill() const;
     bool isEnumValue() const override;
 
 
     std::string mName;
-    ConstantExpression* mValue;
+    ConstantExpression *mValue;
     bool mIsAutoFill;
 
     DISALLOW_COPY_AND_ASSIGN(EnumValue);
diff --git a/Interface.cpp b/Interface.cpp
index 78d42ad..805d81c 100644
--- a/Interface.cpp
+++ b/Interface.cpp
@@ -28,7 +28,6 @@
 #include <unistd.h>
 
 #include <iostream>
-#include <memory>
 #include <sstream>
 
 #include <android-base/logging.h>
@@ -288,8 +287,10 @@
 }
 
 static void emitDigestChain(
-    Formatter& out, const std::string& prefix, const std::vector<const Interface*>& chain,
-    std::function<std::string(std::unique_ptr<ConstantExpression>)> byteToString) {
+        Formatter &out,
+        const std::string &prefix,
+        const std::vector<const Interface *> &chain,
+        std::function<std::string(const ConstantExpression &)> byteToString) {
     out.join(chain.begin(), chain.end(), ",\n", [&] (const auto &iface) {
         const Hash &hash = Hash::getHash(iface->location().begin().filename());
         out << prefix;
@@ -318,8 +319,8 @@
             std::vector<const Interface *> chain = typeChain();
             out << "_hidl_cb(";
             out.block([&] {
-                emitDigestChain(out, "(" + digestType->getInternalDataCppType() + ")", chain,
-                                [](const auto& e) { return e->cppValue(); });
+                emitDigestChain(out, "(" + digestType->getInternalDataCppType() + ")",
+                    chain, [](const auto &e){return e.cppValue();});
             });
             out << ");\n";
             out << "return ::android::hardware::Void();\n";
@@ -332,7 +333,7 @@
             out.indent(2, [&] {
                 // No need for dimensions when elements are explicitly provided.
                 emitDigestChain(out, "new " + digestType->getJavaType(false /* forInitializer */),
-                                chain, [](const auto& e) { return e->javaValue(); });
+                    chain, [](const auto &e){return e.javaValue();});
             });
             out << "));\n";
         } } } /* javaImpl */
diff --git a/Scope.cpp b/Scope.cpp
index 1cee4f8..13a6f28 100644
--- a/Scope.cpp
+++ b/Scope.cpp
@@ -200,9 +200,5 @@
     return false;
 }
 
-ConstantExpression* LocalIdentifier::constExpr() const {
-    return nullptr;
-}
-
 }  // namespace android
 
diff --git a/Scope.h b/Scope.h
index 6a34a59..599182f 100644
--- a/Scope.h
+++ b/Scope.h
@@ -25,7 +25,6 @@
 
 namespace android {
 
-struct ConstantExpression;
 struct Formatter;
 struct Interface;
 struct LocalIdentifier;
@@ -89,8 +88,6 @@
     LocalIdentifier();
     virtual ~LocalIdentifier();
     virtual bool isEnumValue() const;
-
-    virtual ConstantExpression* constExpr() const;
 };
 
 }  // namespace android
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index 9a083c7..805f671 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -425,7 +425,6 @@
     : const_expr
       {
           $$ = new std::vector<ConstantExpression *>;
-          $1->evaluate();
           $$->push_back($1);
       }
     | '{' annotation_const_expr_values '}' { $$ = $2; }
@@ -435,13 +434,11 @@
     : const_expr
       {
           $$ = new std::vector<ConstantExpression *>;
-          $1->evaluate();
           $$->push_back($1);
       }
     | annotation_const_expr_values ',' const_expr
       {
           $$ = $1;
-          $3->evaluate();
           $$->push_back($3);
       }
     ;
@@ -760,7 +757,7 @@
     ;
 
 const_expr
-    : INTEGER                   { $$ = new LiteralConstantExpression($1); }
+    : INTEGER                   { $$ = new ConstantExpression($1); }
     | fqname
       {
           if(!$1->isValidValueName()) {
@@ -769,7 +766,6 @@
                         << @1 << ".\n";
               YYERROR;
           }
-
           if($1->isIdentifier()) {
               std::string identifier = $1->name();
               LocalIdentifier *iden = (*scope)->lookupIdentifier(identifier);
@@ -783,8 +779,8 @@
                             << " is not an enum value at " << @1 << ".\n";
                   YYERROR;
               }
-              $$ = new ReferenceConstantExpression(
-                  Reference<LocalIdentifier>(iden, convertYYLoc(@1)), $1->string());
+              $$ = new ConstantExpression(
+                      *(static_cast<EnumValue *>(iden)->constExpr()), $1->string());
           } else {
               std::string errorMsg;
               EnumValue* v = ast->lookupEnumValue(*$1, &errorMsg, *scope);
@@ -793,42 +789,42 @@
                   YYERROR;
               }
 
-              $$ = new ReferenceConstantExpression(
-                  Reference<LocalIdentifier>(v, convertYYLoc(@1)), $1->string());
+              // TODO: Support Reference
+              $$ = new ConstantExpression(*(v->constExpr()), $1->string());
           }
       }
     | const_expr '?' const_expr ':' const_expr
       {
-          $$ = new TernaryConstantExpression($1, $3, $5);
+          $$ = new ConstantExpression($1, $3, $5);
       }
-    | const_expr LOGICAL_OR const_expr  { $$ = new BinaryConstantExpression($1, "||", $3); }
-    | const_expr LOGICAL_AND const_expr { $$ = new BinaryConstantExpression($1, "&&", $3); }
-    | const_expr '|' const_expr { $$ = new BinaryConstantExpression($1, "|" , $3); }
-    | const_expr '^' const_expr { $$ = new BinaryConstantExpression($1, "^" , $3); }
-    | const_expr '&' const_expr { $$ = new BinaryConstantExpression($1, "&" , $3); }
-    | const_expr EQUALITY const_expr { $$ = new BinaryConstantExpression($1, "==", $3); }
-    | const_expr NEQ const_expr { $$ = new BinaryConstantExpression($1, "!=", $3); }
-    | const_expr '<' const_expr { $$ = new BinaryConstantExpression($1, "<" , $3); }
-    | const_expr '>' const_expr { $$ = new BinaryConstantExpression($1, ">" , $3); }
-    | const_expr LEQ const_expr { $$ = new BinaryConstantExpression($1, "<=", $3); }
-    | const_expr GEQ const_expr { $$ = new BinaryConstantExpression($1, ">=", $3); }
-    | const_expr LSHIFT const_expr { $$ = new BinaryConstantExpression($1, "<<", $3); }
-    | const_expr RSHIFT const_expr { $$ = new BinaryConstantExpression($1, ">>", $3); }
-    | const_expr '+' const_expr { $$ = new BinaryConstantExpression($1, "+" , $3); }
-    | const_expr '-' const_expr { $$ = new BinaryConstantExpression($1, "-" , $3); }
-    | const_expr '*' const_expr { $$ = new BinaryConstantExpression($1, "*" , $3); }
-    | const_expr '/' const_expr { $$ = new BinaryConstantExpression($1, "/" , $3); }
-    | const_expr '%' const_expr { $$ = new BinaryConstantExpression($1, "%" , $3); }
-    | '+' const_expr %prec UNARY_PLUS  { $$ = new UnaryConstantExpression("+", $2); }
-    | '-' const_expr %prec UNARY_MINUS { $$ = new UnaryConstantExpression("-", $2); }
-    | '!' const_expr { $$ = new UnaryConstantExpression("!", $2); }
-    | '~' const_expr { $$ = new UnaryConstantExpression("~", $2); }
+    | const_expr LOGICAL_OR const_expr  { $$ = new ConstantExpression($1, "||", $3); }
+    | const_expr LOGICAL_AND const_expr { $$ = new ConstantExpression($1, "&&", $3); }
+    | const_expr '|' const_expr { $$ = new ConstantExpression($1, "|" , $3); }
+    | const_expr '^' const_expr { $$ = new ConstantExpression($1, "^" , $3); }
+    | const_expr '&' const_expr { $$ = new ConstantExpression($1, "&" , $3); }
+    | const_expr EQUALITY const_expr { $$ = new ConstantExpression($1, "==", $3); }
+    | const_expr NEQ const_expr { $$ = new ConstantExpression($1, "!=", $3); }
+    | const_expr '<' const_expr { $$ = new ConstantExpression($1, "<" , $3); }
+    | const_expr '>' const_expr { $$ = new ConstantExpression($1, ">" , $3); }
+    | const_expr LEQ const_expr { $$ = new ConstantExpression($1, "<=", $3); }
+    | const_expr GEQ const_expr { $$ = new ConstantExpression($1, ">=", $3); }
+    | const_expr LSHIFT const_expr { $$ = new ConstantExpression($1, "<<", $3); }
+    | const_expr RSHIFT const_expr { $$ = new ConstantExpression($1, ">>", $3); }
+    | const_expr '+' const_expr { $$ = new ConstantExpression($1, "+" , $3); }
+    | const_expr '-' const_expr { $$ = new ConstantExpression($1, "-" , $3); }
+    | const_expr '*' const_expr { $$ = new ConstantExpression($1, "*" , $3); }
+    | const_expr '/' const_expr { $$ = new ConstantExpression($1, "/" , $3); }
+    | const_expr '%' const_expr { $$ = new ConstantExpression($1, "%" , $3); }
+    | '+' const_expr %prec UNARY_PLUS  { $$ = new ConstantExpression("+", $2); }
+    | '-' const_expr %prec UNARY_MINUS { $$ = new ConstantExpression("-", $2); }
+    | '!' const_expr { $$ = new ConstantExpression("!", $2); }
+    | '~' const_expr { $$ = new ConstantExpression("~", $2); }
     | '(' const_expr ')' { $$ = $2; }
     | '(' error ')'
       {
         ast->addSyntaxError();
         // to avoid segfaults
-        $$ = ConstantExpression::Zero(ScalarType::KIND_INT32).release();
+        $$ = new ConstantExpression(ConstantExpression::Zero(ScalarType::KIND_INT32));
       }
     ;
 
@@ -1024,7 +1020,7 @@
 
 enum_value
     : valid_identifier { $$ = new EnumValue($1); }
-    | valid_identifier '=' const_expr { $3->evaluate(); $$ = new EnumValue($1, $3); }
+    | valid_identifier '=' const_expr { $$ = new EnumValue($1, $3); }
     ;
 
 enum_values
@@ -1100,8 +1096,6 @@
 
               YYERROR;
           }
-
-          $3->evaluate();
           if (type.isResolved() && type->isArray()) {
               $$ = new ArrayType(static_cast<ArrayType*>(type.get()), $3);
           } else {
@@ -1111,7 +1105,6 @@
     | array_type '[' const_expr ']'
       {
           $$ = $1;
-          $3->evaluate();
           $$->appendDimension($3);
       }
     ;
diff --git a/main.cpp b/main.cpp
index 696b3af..8c4a760 100644
--- a/main.cpp
+++ b/main.cpp
@@ -639,6 +639,16 @@
            fqName.package() == gIManagerPackageFqName.string();
 }
 
+bool isSystemProcessSupportedPackage(const FQName& fqName) {
+    // Technically, so is hidl IBase + IServiceManager, but
+    // these are part of libhidltransport.
+    return fqName.string() == "android.hardware.graphics.allocator@2.0" ||
+           fqName.string() == "android.hardware.graphics.common@1.0" ||
+           fqName.string() == "android.hardware.graphics.mapper@2.0" ||
+           fqName.string() == "android.hardware.renderscript@1.0" ||
+           fqName.string() == "android.hidl.memory@1.0";
+}
+
 bool isSystemPackage(const FQName &package) {
     return package.inPackage("android.hidl") ||
            package.inPackage("android.system") ||
@@ -708,6 +718,7 @@
 static void generateAndroidBpLibSection(
         Formatter &out,
         bool generateVendor,
+        const FQName &packageFQName,
         const std::string &libraryName,
         const std::string &genSourceName,
         const std::string &genHeaderName,
@@ -729,6 +740,9 @@
         out << "vndk: ";
         out.block([&]() {
             out << "enabled: true,\n";
+            if (isSystemProcessSupportedPackage(packageFQName)) {
+                out << "support_system_process: true,\n";
+            }
         }) << ",\n";
     }
     out << "shared_libs: [\n";
@@ -885,6 +899,7 @@
         generateAndroidBpLibSection(
             out,
             false /* generateVendor */,
+            packageFQName,
             libraryName,
             genSourceName,
             genHeaderName,
@@ -908,6 +923,7 @@
             generateAndroidBpLibSection(
                 out,
                 true /* generateVendor */,
+                packageFQName,
                 libraryName,
                 genSourceName,
                 genHeaderName,