Migrate IRGenerator::setRefKind to Analysis::MakeAssignmentExpr.

Fundamentally this function wasn't a generic "set the refKind on an
expression" at all; it was intended specifically as "this expression
must be IsAssignable and contain a VariableReference." Also, it needs
nothing at all from the IRGenerator. Moving it out is important because
it will be used by Make functions for things like VariableReference.

Change-Id: I52d613989cd5fb0feb2e98ae454943cdacb9404b
Bug: skia:11342
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/376841
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/sksl/SkSLAnalysis.cpp b/src/sksl/SkSLAnalysis.cpp
index 8002ea5..77bd11c 100644
--- a/src/sksl/SkSLAnalysis.cpp
+++ b/src/sksl/SkSLAnalysis.cpp
@@ -528,6 +528,21 @@
     RefKindWriter{refKind}.visitExpression(*expr);
 }
 
+bool Analysis::MakeAssignmentExpr(Expression* expr,
+                                  VariableReference::RefKind kind,
+                                  ErrorReporter* errors) {
+    Analysis::AssignmentInfo info;
+    if (!Analysis::IsAssignable(*expr, &info, errors)) {
+        return false;
+    }
+    if (!info.fAssignedVar) {
+        errors->error(expr->fOffset, "can't assign to expression '" + expr->description() + "'");
+        return false;
+    }
+    info.fAssignedVar->setRefKind(kind);
+    return true;
+}
+
 bool Analysis::IsTrivialExpression(const Expression& expr) {
     return expr.is<IntLiteral>() ||
            expr.is<FloatLiteral>() ||
diff --git a/src/sksl/SkSLAnalysis.h b/src/sksl/SkSLAnalysis.h
index 190593b..d33f3c8 100644
--- a/src/sksl/SkSLAnalysis.h
+++ b/src/sksl/SkSLAnalysis.h
@@ -65,7 +65,12 @@
     static bool IsAssignable(Expression& expr, AssignmentInfo* info,
                              ErrorReporter* errors = nullptr);
 
+    // Updates the `refKind` field of exactly one VariableReference inside `expr`.
+    // `expr` must be `IsAssignable`; returns an error otherwise.
+    static bool MakeAssignmentExpr(Expression* expr, VariableRefKind kind, ErrorReporter* errors);
+
     // Updates the `refKind` field of every VariableReference found within `expr`.
+    // `expr` is allowed to have zero, one, or multiple VariableReferences.
     static void UpdateRefKind(Expression* expr, VariableRefKind refKind);
 
     // A "trivial" expression is one where we'd feel comfortable cloning it multiple times in
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 7534900..a0e0ae2 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -1824,9 +1824,12 @@
         return nullptr;
     }
     bool isAssignment = op.isAssignment();
-    if (isAssignment && !this->setRefKind(*left, op.kind() != Token::Kind::TK_EQ
-                                                 ? VariableReference::RefKind::kReadWrite
-                                                 : VariableReference::RefKind::kWrite)) {
+    if (isAssignment &&
+        !Analysis::MakeAssignmentExpr(left.get(),
+                                      op.kind() != Token::Kind::TK_EQ
+                                              ? VariableReference::RefKind::kReadWrite
+                                              : VariableReference::RefKind::kWrite,
+                                      &fContext.fErrors)) {
         return nullptr;
     }
     if (!determine_binary_type(fContext, this->settings().fAllowNarrowingConversions, op,
@@ -2020,9 +2023,11 @@
         }
         const Modifiers& paramModifiers = function.parameters()[i]->modifiers();
         if (paramModifiers.fFlags & Modifiers::kOut_Flag) {
-            if (!this->setRefKind(*arguments[i], paramModifiers.fFlags & Modifiers::kIn_Flag
-                                                          ? VariableReference::RefKind::kReadWrite
-                                                          : VariableReference::RefKind::kPointer)) {
+            if (!Analysis::MakeAssignmentExpr(arguments[i].get(),
+                                              paramModifiers.fFlags & Modifiers::kIn_Flag
+                                                      ? VariableReference::RefKind::kReadWrite
+                                                      : VariableReference::RefKind::kPointer,
+                                              &fContext.fErrors)) {
                 return nullptr;
             }
         }
@@ -2164,7 +2169,8 @@
                                             "' cannot operate on '" + baseType.displayName() + "'");
                 return nullptr;
             }
-            if (!this->setRefKind(*base, VariableReference::RefKind::kReadWrite)) {
+            if (!Analysis::MakeAssignmentExpr(base.get(), VariableReference::RefKind::kReadWrite,
+                                              &fContext.fErrors)) {
                 return nullptr;
             }
             break;
@@ -2175,7 +2181,8 @@
                                             "' cannot operate on '" + baseType.displayName() + "'");
                 return nullptr;
             }
-            if (!this->setRefKind(*base, VariableReference::RefKind::kReadWrite)) {
+            if (!Analysis::MakeAssignmentExpr(base.get(), VariableReference::RefKind::kReadWrite,
+                                              &fContext.fErrors)) {
                 return nullptr;
             }
             break;
@@ -2505,7 +2512,8 @@
                                     "' cannot operate on '" + baseType.displayName() + "'");
         return nullptr;
     }
-    if (!this->setRefKind(*base, VariableReference::RefKind::kReadWrite)) {
+    if (!Analysis::MakeAssignmentExpr(base.get(), VariableReference::RefKind::kReadWrite,
+                                      &fContext.fErrors)) {
         return nullptr;
     }
     return std::make_unique<PostfixExpression>(std::move(base), op);
@@ -2534,17 +2542,6 @@
     }
 }
 
-bool IRGenerator::setRefKind(Expression& expr, VariableReference::RefKind kind) {
-    Analysis::AssignmentInfo info;
-    if (!Analysis::IsAssignable(expr, &info, &this->errorReporter())) {
-        return false;
-    }
-    if (info.fAssignedVar) {
-        info.fAssignedVar->setRefKind(kind);
-    }
-    return true;
-}
-
 void IRGenerator::findAndDeclareBuiltinVariables() {
     class BuiltinVariableScanner : public ProgramVisitor {
     public: