Fix crash when comparing against a negated constant vector.

This CL solves the fuzzer crash. Constant propagation of the negative
sign into the vector will be investigated in a followup CL.

This CL also adds a few cleanups into IRGenerator::constantFold.

Change-Id: If73a4fe2a5777265e7d43cc4f482653a38cb59af
Bug: oss-fuzz:26830, oss-fuzz:26789
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/332261
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 10c5077..339c0de 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -1726,9 +1726,9 @@
                                                       const Expression& right) const {
     // If the left side is a constant boolean literal, the right side does not need to be constant
     // for short circuit optimizations to allow the constant to be folded.
-    if (left.kind() == Expression::Kind::kBoolLiteral && !right.isCompileTimeConstant()) {
+    if (left.is<BoolLiteral>() && !right.isCompileTimeConstant()) {
         return short_circuit_boolean(fContext, left, op, right);
-    } else if (right.kind() == Expression::Kind::kBoolLiteral && !left.isCompileTimeConstant()) {
+    } else if (right.is<BoolLiteral>() && !left.isCompileTimeConstant()) {
         // There aren't side effects in SKSL within expressions, so (left OP right) is equivalent to
         // (right OP left) for short-circuit optimizations
         return short_circuit_boolean(fContext, right, op, left);
@@ -1742,8 +1742,7 @@
     // precision to calculate the results and hope the result makes sense. The plan is to move the
     // Skia caps into SkSL, so we have access to all of them including the precisions of the various
     // types, which will let us be more intelligent about this.
-    if (left.kind() == Expression::Kind::kBoolLiteral &&
-        right.kind() == Expression::Kind::kBoolLiteral) {
+    if (left.is<BoolLiteral>() && right.is<BoolLiteral>()) {
         bool leftVal  = left.as<BoolLiteral>().value();
         bool rightVal = right.as<BoolLiteral>().value();
         bool result;
@@ -1753,15 +1752,14 @@
             case Token::Kind::TK_LOGICALXOR: result = leftVal ^  rightVal; break;
             default: return nullptr;
         }
-        return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fOffset, result));
+        return std::make_unique<BoolLiteral>(fContext, left.fOffset, result);
     }
     #define RESULT(t, op) std::make_unique<t ## Literal>(fContext, left.fOffset, \
                                                          leftVal op rightVal)
     #define URESULT(t, op) std::make_unique<t ## Literal>(fContext, left.fOffset, \
                                                           (uint32_t) leftVal op   \
                                                           (uint32_t) rightVal)
-    if (left.kind() == Expression::Kind::kIntLiteral &&
-        right.kind() == Expression::Kind::kIntLiteral) {
+    if (left.is<IntLiteral>() && right.is<IntLiteral>()) {
         int64_t leftVal  = left.as<IntLiteral>().value();
         int64_t rightVal = right.as<IntLiteral>().value();
         switch (op) {
@@ -1814,8 +1812,7 @@
                 return nullptr;
         }
     }
-    if (left.kind() == Expression::Kind::kFloatLiteral &&
-        right.kind() == Expression::Kind::kFloatLiteral) {
+    if (left.is<FloatLiteral>() && right.is<FloatLiteral>()) {
         SKSL_FLOAT leftVal  = left.as<FloatLiteral>().value();
         SKSL_FLOAT rightVal = right.as<FloatLiteral>().value();
         switch (op) {
@@ -1842,19 +1839,25 @@
     if (leftType.typeKind() == Type::TypeKind::kVector && leftType.componentType().isFloat() &&
         leftType == rightType) {
         ExpressionArray args;
-        #define RETURN_VEC_COMPONENTWISE_RESULT(op)                                              \
-            for (int i = 0; i < leftType.columns(); i++) {                                       \
-                SKSL_FLOAT value = left.getFVecComponent(i) op right.getFVecComponent(i);        \
-                args.push_back(std::make_unique<FloatLiteral>(fContext, /*offset=*/-1, value));  \
-            }                                                                                    \
-            return std::make_unique<Constructor>(/*offset=*/-1, &leftType, std::move(args))
+        #define RETURN_VEC_COMPONENTWISE_RESULT(op)                                             \
+            for (int i = 0; i < leftType.columns(); i++) {                                      \
+                SKSL_FLOAT value = left.getFVecComponent(i) op right.getFVecComponent(i);       \
+                args.push_back(std::make_unique<FloatLiteral>(fContext, left.fOffset, value));  \
+            }                                                                                   \
+            return std::make_unique<Constructor>(left.fOffset, &leftType, std::move(args))
         switch (op) {
             case Token::Kind::TK_EQEQ:
-                return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
-                                                            left.compareConstant(fContext, right)));
+                if (left.kind() == right.kind()) {
+                    return std::make_unique<BoolLiteral>(fContext, left.fOffset,
+                                                         left.compareConstant(fContext, right));
+                }
+                return nullptr;
             case Token::Kind::TK_NEQ:
-                return std::unique_ptr<Expression>(new BoolLiteral(fContext, -1,
-                                                           !left.compareConstant(fContext, right)));
+                if (left.kind() == right.kind()) {
+                    return std::make_unique<BoolLiteral>(fContext, left.fOffset,
+                                                         !left.compareConstant(fContext, right));
+                }
+                return nullptr;
             case Token::Kind::TK_PLUS:  RETURN_VEC_COMPONENTWISE_RESULT(+);
             case Token::Kind::TK_MINUS: RETURN_VEC_COMPONENTWISE_RESULT(-);
             case Token::Kind::TK_STAR:  RETURN_VEC_COMPONENTWISE_RESULT(*);
@@ -1872,16 +1875,17 @@
             default:
                 return nullptr;
         }
+        #undef RETURN_VEC_COMPONENTWISE_RESULT
     }
     if (leftType.typeKind() == Type::TypeKind::kMatrix &&
         rightType.typeKind() == Type::TypeKind::kMatrix &&
         left.kind() == right.kind()) {
         switch (op) {
             case Token::Kind::TK_EQEQ:
-                return std::make_unique<BoolLiteral>(fContext, /*offset=*/-1,
+                return std::make_unique<BoolLiteral>(fContext, left.fOffset,
                                                      left.compareConstant(fContext, right));
             case Token::Kind::TK_NEQ:
-                return std::make_unique<BoolLiteral>(fContext, /*offset=*/-1,
+                return std::make_unique<BoolLiteral>(fContext, left.fOffset,
                                                      !left.compareConstant(fContext, right));
             default:
                 return nullptr;