Implement postfix ++/--, and use the correct 1 for floats

Change-Id: I0e6e8205998f3058cb59e279704e23989bccc66b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/214192
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp
index c724483..5c877a7 100644
--- a/src/sksl/SkSLByteCodeGenerator.cpp
+++ b/src/sksl/SkSLByteCodeGenerator.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "src/sksl/SkSLByteCodeGenerator.h"
+#include "src/sksl/SkSLInterpreter.h"
 
 namespace SkSL {
 
@@ -379,8 +380,7 @@
 void ByteCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
     this->align(4, 3);
     this->write(ByteCodeInstruction::kPushImmediate);
-    union { float f; uint32_t u; } pun = { (float) f.fValue };
-    this->write32(pun.u);
+    this->write32(Interpreter::Value((float) f.fValue).fUnsigned);
 }
 
 void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
@@ -411,12 +411,13 @@
     switch (p.fOperator) {
         case Token::Kind::PLUSPLUS: // fall through
         case Token::Kind::MINUSMINUS: {
+            SkASSERT(slot_count(p.fOperand->fType) == 1);
             std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
             lvalue->load();
             this->align(4, 3);
             this->write(ByteCodeInstruction::kPushImmediate);
-            this->write32(1);
-            SkASSERT(slot_count(p.fOperand->fType) == 1);
+            this->write32(type_category(p.fType) == TypeCategory::kFloat
+                            ? Interpreter::Value(1.0f).fUnsigned : 1);
             if (p.fOperator == Token::Kind::PLUSPLUS) {
                 this->writeTypedInstruction(p.fType,
                                             ByteCodeInstruction::kAddI,
@@ -448,8 +449,38 @@
 }
 
 void ByteCodeGenerator::writePostfixExpression(const PostfixExpression& p) {
-    // not yet implemented
-    abort();
+    switch (p.fOperator) {
+        case Token::Kind::PLUSPLUS: // fall through
+        case Token::Kind::MINUSMINUS: {
+            SkASSERT(slot_count(p.fOperand->fType) == 1);
+            std::unique_ptr<LValue> lvalue = this->getLValue(*p.fOperand);
+            lvalue->load();
+            this->write(ByteCodeInstruction::kDup);
+            this->align(4, 3);
+            this->write(ByteCodeInstruction::kPushImmediate);
+            this->write32(type_category(p.fType) == TypeCategory::kFloat
+                            ? Interpreter::Value(1.0f).fUnsigned : 1);
+            if (p.fOperator == Token::Kind::PLUSPLUS) {
+                this->writeTypedInstruction(p.fType,
+                                            ByteCodeInstruction::kAddI,
+                                            ByteCodeInstruction::kAddI,
+                                            ByteCodeInstruction::kAddF,
+                                            1);
+            } else {
+                this->writeTypedInstruction(p.fType,
+                                            ByteCodeInstruction::kSubtractI,
+                                            ByteCodeInstruction::kSubtractI,
+                                            ByteCodeInstruction::kSubtractF,
+                                            1);
+            }
+            lvalue->store();
+            this->write(ByteCodeInstruction::kPop);
+            this->write8(1);
+            break;
+        }
+        default:
+            SkASSERT(false);
+    }
 }
 
 void ByteCodeGenerator::writeSwizzle(const Swizzle& s) {
diff --git a/tests/SkSLInterpreterTest.cpp b/tests/SkSLInterpreterTest.cpp
index 0fd7418..d513bc9 100644
--- a/tests/SkSLInterpreterTest.cpp
+++ b/tests/SkSLInterpreterTest.cpp
@@ -267,6 +267,11 @@
          495, 0, 0, 0);
 }
 
+DEF_TEST(SkSLInterpreterPrefixPostfix, r) {
+    test(r, "void main(inout half4 color) { color.r = ++color.g; }", 1, 2, 3, 4, 3, 3, 3, 4);
+    test(r, "void main(inout half4 color) { color.r = color.g++; }", 1, 2, 3, 4, 2, 3, 3, 4);
+}
+
 DEF_TEST(SkSLInterpreterSwizzle, r) {
     test(r, "void main(inout half4 color) { color = color.abgr; }", 1, 2, 3, 4, 4, 3, 2, 1);
     test(r, "void main(inout half4 color) { color.rgb = half4(5, 6, 7, 8).bbg; }", 1, 2, 3, 4, 7, 7,