Improve error handling in SkSL ByteCode

- Allow for $floatLiteral and $intLiteral when determining type
  categories. These could slip into the IR, leading to asserts.
- We weren't propagating the source text in specialize(), so errors in
  the ByteCodeGenerator would actually assert about a missing fSource.
  It's held by unique_ptr on Program, so we wastefully clone the
  string, but we don't have that many specializations yet, so not too
  bad?

Change-Id: I9c79acfb084e6dc8628625dea039c085ec46dba7
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/265598
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/samplecode/Sample3D.cpp b/samplecode/Sample3D.cpp
index 252cf5e..4478386 100644
--- a/samplecode/Sample3D.cpp
+++ b/samplecode/Sample3D.cpp
@@ -406,9 +406,6 @@
     }
 
     void onDrawContent(SkCanvas* canvas) override {
-        if (canvas->getGrContext() == nullptr) {
-            return;
-        }
         SkM44 clickM = canvas->experimental_getLocalToDevice();
 
         canvas->save();
diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp
index d692daf..36a1338 100644
--- a/src/sksl/SkSLByteCodeGenerator.cpp
+++ b/src/sksl/SkSLByteCodeGenerator.cpp
@@ -19,12 +19,17 @@
         default:
             if (type.fName == "bool") {
                 return TypeCategory::kBool;
-            } else if (type.fName == "int" || type.fName == "short") {
+            } else if (type.fName == "int" ||
+                       type.fName == "short" ||
+                       type.fName == "$intLiteral") {
                 return TypeCategory::kSigned;
-            } else if (type.fName == "uint" || type.fName == "ushort") {
+            } else if (type.fName == "uint" ||
+                       type.fName == "ushort") {
                 return TypeCategory::kUnsigned;
             } else {
-                SkASSERT(type.fName == "float" || type.fName == "half");
+                SkASSERT(type.fName == "float" ||
+                         type.fName == "half" ||
+                         type.fName == "$floatLiteral");
                 return TypeCategory::kFloat;
             }
             ABORT("unsupported type: %s\n", type.displayName().c_str());
@@ -979,7 +984,8 @@
 void ByteCodeGenerator::writeIntrinsicCall(const FunctionCall& c) {
     auto found = fIntrinsics.find(c.fFunction.fName);
     if (found == fIntrinsics.end()) {
-        fErrors.error(c.fOffset, "unsupported intrinsic function");
+        fErrors.error(c.fOffset, String::printf("Unsupported intrinsic: '%s'",
+                                                String(c.fFunction.fName).c_str()));
         return;
     }
     int count = SlotCount(c.fArguments[0]->fType);
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index d4c0e2e..7bfdce1 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -1481,8 +1481,9 @@
     for (auto iter = inputs.begin(); iter != inputs.end(); ++iter) {
         settings.fArgs.insert(*iter);
     }
+    std::unique_ptr<String> sourceCopy(new String(*program.fSource));
     std::unique_ptr<Program> result(new Program(program.fKind,
-                                                nullptr,
+                                                std::move(sourceCopy),
                                                 settings,
                                                 program.fContext,
                                                 program.fInheritedElements,
@@ -1621,9 +1622,12 @@
     if (!this->optimize(program)) {
         return nullptr;
     }
+    fSource = program.fSource.get();
     std::unique_ptr<ByteCode> result(new ByteCode());
     ByteCodeGenerator cg(fContext.get(), &program, this, result.get());
-    if (cg.generateCode()) {
+    bool success = cg.generateCode();
+    fSource = nullptr;
+    if (success) {
         return result;
     }
 #else