From 51c10d29c38742152e99901a5e3cdfc0a3e4f729 Mon Sep 17 00:00:00 2001
From: Jesper Gravgaard <jg@ramboll.com>
Date: Fri, 10 May 2019 11:20:37 +0200
Subject: [PATCH] Working on fixing type conversion casting. Still a work in
 progress!

---
 .../model/types/SymbolTypeConversion.java     | 12 +++++++---
 .../passes/Pass2ConstantSimplification.java   |  8 +++----
 .../passes/PassNAddNumberTypeConversions.java | 24 +++++++++++--------
 .../passes/PassNAddTypeConversionsNew.java    |  2 ++
 4 files changed, 29 insertions(+), 17 deletions(-)

diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
index 15c35ad73..9e136c58b 100644
--- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
+++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeConversion.java
@@ -27,6 +27,7 @@ public class SymbolTypeConversion {
     * @return The type resulting from a binary operator performed on the two parameters
     */
    public static SymbolType convertedMathType(SymbolTypeInteger type1, SymbolTypeInteger type2) {
+      // If any of the two types are unresolved - return an unresolved result
       if(SymbolType.NUMBER.equals(type1) || SymbolType.NUMBER.equals(type2)) {
          return SymbolType.NUMBER;
       }
@@ -57,7 +58,7 @@ public class SymbolTypeConversion {
    }
 
    /**
-    * Find the integer type that results from a binary operator according to the special number type conversion https://gitlab.com/camelot/kickc/issues/181
+    * Find the integer type that a number operand in a binary operator should be converted/cast to according to number type conversion https://gitlab.com/camelot/kickc/issues/181
     *
     * @param left The left value
     * @param right The right value
@@ -65,7 +66,7 @@ public class SymbolTypeConversion {
     * @param currentStmt The current statement (used only for exception context)
     * @return a non-null fixed integer type if a number type conversion is relevant.
     */
-   public static SymbolType convertedNumberType(RValue left, RValue right, ProgramScope symbols, Statement currentStmt) {
+   public static SymbolType getNumberCastType(RValue left, RValue right, ProgramScope symbols, Statement currentStmt) {
 
       SymbolType leftType = SymbolTypeInference.inferType(symbols, left);
       SymbolType rightType = SymbolTypeInference.inferType(symbols, right);
@@ -80,6 +81,10 @@ public class SymbolTypeConversion {
             return null;
          }
 
+         // Treat pointers like WORD
+         if(leftType instanceof SymbolTypePointer) leftType = SymbolType.WORD;
+         if(rightType instanceof SymbolTypePointer) rightType = SymbolType.WORD;
+
          RValue numberVal;
          SymbolTypeIntegerFixed fixedType;
          if(SymbolType.NUMBER.equals(leftType) && SymbolType.isInteger(rightType)) {
@@ -125,7 +130,8 @@ public class SymbolTypeConversion {
                      } else {
                         smallestUnsignedType = SymbolTypeIntegerFixed.getSmallestUnsigned(value);
                      }
-                     return smallestUnsignedType.getBits() > fixedType.getBits() ? smallestUnsignedType : fixedType;
+                     return smallestUnsignedType;
+                     //return smallestUnsignedType.getBits() > fixedType.getBits() ? smallestUnsignedType : fixedType;
                   }
                } else {
                   throw new InternalError("Non-number constant has type number " + right.toString(), currentStmt);
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantSimplification.java
index 8b748d28e..cb4490626 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantSimplification.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantSimplification.java
@@ -29,13 +29,13 @@ public class Pass2ConstantSimplification extends Pass2SsaOptimization {
                // Found a candidate!!
                ConstantInteger intOperand = (ConstantInteger) unary.getOperand();
                getLog().append("Simplifying constant integer increment "+unary);
-               programValue.set(new ConstantInteger(intOperand.getValue()+1));
+               programValue.set(new ConstantInteger(intOperand.getValue()+1, intOperand.getType()));
                optimized[0] = true;
             } else if(Operators.DECREMENT.equals(unary.getOperator()) && unary.getOperand() instanceof ConstantInteger) {
                // Found a candidate!!
                ConstantInteger intOperand = (ConstantInteger) unary.getOperand();
                getLog().append("Simplifying constant integer decrement "+unary);
-               programValue.set(new ConstantInteger(intOperand.getValue()+1));
+               programValue.set(new ConstantInteger(intOperand.getValue()-1, intOperand.getType()));
                optimized[0] = true;
             }
          } else if(programValue.get() instanceof ConstantBinary) {
@@ -43,10 +43,10 @@ public class Pass2ConstantSimplification extends Pass2SsaOptimization {
             if(Operators.MULTIPLY.equals(binary.getOperator())) {
                if(binary.getLeft() instanceof ConstantInteger && ((ConstantInteger) binary.getLeft()).getValue() == 0) {
                   getLog().append("Simplifying constant multiply by zero " + binary);
-                  programValue.set(new ConstantInteger(0L));
+                  programValue.set(new ConstantInteger(0L, binary.getType(getScope())));
                } else if(binary.getRight() instanceof ConstantInteger && ((ConstantInteger) binary.getRight()).getValue() == 0) {
                   getLog().append("Simplifying constant multiply by zero " + binary);
-                  programValue.set(new ConstantInteger(0L));
+                  programValue.set(new ConstantInteger(0L, binary.getType(getScope())));
                }
             } else if(Operators.PLUS.equals(binary.getOperator())) {
                if(binary.getLeft() instanceof ConstantInteger && ((ConstantInteger) binary.getLeft()).getValue() == 0) {
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
index 6854e09b0..7a69f1fd4 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddNumberTypeConversions.java
@@ -6,9 +6,10 @@ import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
 import dk.camelot64.kickc.model.types.SymbolType;
 import dk.camelot64.kickc.model.types.SymbolTypeConversion;
 import dk.camelot64.kickc.model.types.SymbolTypeInference;
-import dk.camelot64.kickc.model.types.SymbolTypePointer;
 import dk.camelot64.kickc.model.values.RValue;
 
+import java.util.concurrent.atomic.AtomicBoolean;
+
 /**
  * Add casts to {@link SymbolType#NUMBER} expressions that meet a typed value in a binary expression (including assignment)
  */
@@ -20,28 +21,31 @@ public class PassNAddNumberTypeConversions extends Pass2SsaOptimization {
 
    @Override
    public boolean step() {
+      AtomicBoolean modified = new AtomicBoolean(false);
       ProgramExpressionIterator.execute(getProgram(), (binaryExpression, currentStmt, stmtIt, currentBlock) -> {
          if(binaryExpression instanceof ProgramExpressionBinary) {
             ProgramExpressionBinary binary = (ProgramExpressionBinary) binaryExpression;
             RValue left = binary.getLeft();
             RValue right = binary.getRight();
-            SymbolType conversionType = SymbolTypeConversion.convertedNumberType(left, right, getScope(), currentStmt);
-            if(conversionType != null) {
+            SymbolType castType = SymbolTypeConversion.getNumberCastType(left, right, getScope(), currentStmt);
+            if(castType != null) {
                // Convert both left and right to the found type
                SymbolType leftType = SymbolTypeInference.inferType(getProgram().getScope(), left);
-               if(!leftType.equals(conversionType) && !(leftType instanceof SymbolTypePointer)) {
-                  getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getLeft().toString() + " in " + (currentStmt==null?"":currentStmt.toString(getProgram(), false)));
-                  binary.addLeftCast(conversionType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope());
+               if(SymbolType.NUMBER.equals(leftType)) {
+                  getLog().append("Adding number conversion cast (" + castType + ") " + binary.getLeft().toString() + " in " + (currentStmt==null?"":currentStmt.toString(getProgram(), false)));
+                  binary.addLeftCast(castType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope());
+                  modified.set(true);
                }
                SymbolType rightType = SymbolTypeInference.inferType(getProgram().getScope(), right);
-               if(!rightType.equals(conversionType) && !(rightType instanceof SymbolTypePointer)) {
-                  getLog().append("Adding number conversion cast (" + conversionType + ") " + binary.getRight().toString() + " in " + ((currentStmt==null)?"":currentStmt.toString(getProgram(), false)));
-                  binary.addRightCast(conversionType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope());
+               if(rightType.equals(SymbolType.NUMBER)) {
+                  getLog().append("Adding number conversion cast (" + castType + ") " + binary.getRight().toString() + " in " + ((currentStmt==null)?"":currentStmt.toString(getProgram(), false)));
+                  binary.addRightCast(castType, stmtIt, currentBlock==null?null:currentBlock.getScope(), getScope());
+                  modified.set(true);
                }
             }
          }
       });
-      return false;
+      return modified.get();
    }
 
 }
diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
index 4f4e3d1b6..ee10bd5c5 100644
--- a/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
+++ b/src/main/java/dk/camelot64/kickc/passes/PassNAddTypeConversionsNew.java
@@ -32,6 +32,7 @@ public class PassNAddTypeConversionsNew extends Pass2SsaOptimization {
                binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope());
             }
 
+            /*
             if(SymbolType.isInteger(leftType) && SymbolType.isInteger(rightType)) {
                SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType);
                if(conversionType != null && !SymbolType.NUMBER.equals(conversionType)) {
@@ -54,6 +55,7 @@ public class PassNAddTypeConversionsNew extends Pass2SsaOptimization {
                   }
                }
             }
+            */
          }
       });
       return false;