From 4597275ed22daa2c2ed2e0fe7c3cd967e071ddc7 Mon Sep 17 00:00:00 2001
From: Gary Frost <frost.gary@gmail.com>
Date: Wed, 23 Jan 2013 21:30:07 +0000
Subject: [PATCH] Max Grossman discovered/reported that Aparapi did not support
 do{}while(??). This is an attempt to rectify that.  Added a junit test and a
 first implementation

---
 .../src/java/com/amd/aparapi/BlockWriter.java | 13 +++++++
 .../java/com/amd/aparapi/ExpressionList.java  | 24 +++++++++++-
 .../java/com/amd/aparapi/InstructionSet.java  | 17 ++++++++-
 .../java/com/amd/aparapi/test/DoWhile.java    | 38 +++++++++++++++++++
 4 files changed, 89 insertions(+), 3 deletions(-)
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/DoWhile.java

diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/BlockWriter.java b/com.amd.aparapi/src/java/com/amd/aparapi/BlockWriter.java
index e2336381..71fab3fc 100644
--- a/com.amd.aparapi/src/java/com/amd/aparapi/BlockWriter.java
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/BlockWriter.java
@@ -60,6 +60,7 @@ import com.amd.aparapi.InstructionSet.CloneInstruction;
 import com.amd.aparapi.InstructionSet.CompositeArbitraryScopeInstruction;
 import com.amd.aparapi.InstructionSet.CompositeEmptyLoopInstruction;
 import com.amd.aparapi.InstructionSet.CompositeForEclipseInstruction;
+import com.amd.aparapi.InstructionSet.CompositeDoWhileInstruction;
 import com.amd.aparapi.InstructionSet.CompositeForSunInstruction;
 import com.amd.aparapi.InstructionSet.CompositeIfElseInstruction;
 import com.amd.aparapi.InstructionSet.CompositeIfInstruction;
@@ -291,6 +292,18 @@ abstract class BlockWriter{
             write("}");
 
          }
+      } else if (instruction instanceof CompositeDoWhileInstruction) {
+         newLine();
+         write("do");
+         Instruction blockStart = instruction.getFirstChild();
+         Instruction blockEnd = instruction.getLastChild();
+         writeBlock(blockStart, blockEnd);
+         write("while(");
+         writeConditional(((CompositeInstruction) instruction).getBranchSet(), true);
+         write(");");
+         newLine();
+         
+         
       }
    }
 
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/ExpressionList.java b/com.amd.aparapi/src/java/com/amd/aparapi/ExpressionList.java
index bceada5d..ac28e944 100644
--- a/com.amd.aparapi/src/java/com/amd/aparapi/ExpressionList.java
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/ExpressionList.java
@@ -430,7 +430,7 @@ class ExpressionList{
 
                if (tail != null && tail.isBranch() && tail.asBranch().isReverseConditional()) {
                   /**
-                   * This looks like an eclipse style for/while loop
+                   * This looks like an eclipse style for/while loop or possibly a do{}while()
                    * <pre>
                    * eclipse for (INIT,??,DELTA){BODY} ...
                    *    [INIT] >> [BODY] [DELTA] ?? ?< ...
@@ -446,6 +446,10 @@ class ExpressionList{
                    *    >> [BODY] ?? ?< ...
                    *     -------->
                    *       <----------
+                   * do {BODY} while(??)
+                   *    [BODY] ?? ?< ...
+                   *    <-----------
+                   *    
                    * </pre>
                    **/
                   BranchSet branchSet = ((ConditionalBranch) tail.asBranch()).getOrCreateBranchSet();
@@ -487,6 +491,24 @@ class ExpressionList{
                            handled = true;
                         }
                      }
+                     if (!handled){
+                        // do{}while()_ do not require any previous instruction
+                       if (loopTop.getPrevExpr() ==null){
+                           throw new IllegalStateException("might be a dowhile with no provious expression");
+                         
+                        }else if (!(loopTop.getPrevExpr().isBranch() && loopTop.getPrevExpr().asBranch().isForwardUnconditional())){
+                           if (doesNotContainCompositeOrBranch(branchSet.getTarget().getRootExpr(), branchSet.getFirst().getPrevExpr())) {
+                              loopTop = loopTop.getPrevExpr();
+                               branchSet.unhook();
+                              addAsComposites(ByteCode.COMPOSITE_DO_WHILE, loopTop, branchSet);
+                              handled = true;
+                           }
+                        }else{
+                           throw new IllegalStateException("might be mistaken for a do while!");
+                        }
+                    
+                         
+                     }
                   }
                }
                if (!handled && _instruction.isForwardConditionalBranchTarget() && tail.isBranch()
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/InstructionSet.java b/com.amd.aparapi/src/java/com/amd/aparapi/InstructionSet.java
index 755a45db..573ee740 100644
--- a/com.amd.aparapi/src/java/com/amd/aparapi/InstructionSet.java
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/InstructionSet.java
@@ -602,7 +602,7 @@ class InstructionSet{
       COMPOSITE_IF, //
       COMPOSITE_IF_ELSE, //
       COMPOSITE_FOR_SUN, //
-      COMPOSITE_FOR_ECLIPSE, //
+      COMPOSITE_FOR_ECLIPSE,// 
       COMPOSITE_ARBITRARY_SCOPE, //
       COMPOSITE_WHILE, //
       CLONE, //
@@ -613,7 +613,8 @@ class InstructionSet{
       FIELD_ARRAY_ELEMENT_INCREMENT, //
       FIELD_ARRAY_ELEMENT_ASSIGN, //
       HEAD, //
-      COMPOSITE_EMPTY_LOOP;
+      COMPOSITE_EMPTY_LOOP,//
+      COMPOSITE_DO_WHILE;
 
       private Class<?> clazz;
 
@@ -835,6 +836,9 @@ class InstructionSet{
             case COMPOSITE_EMPTY_LOOP:
                compositeInstruction = new CompositeEmptyLoopInstruction(_methodModel, _firstChild, _lastChild, _branchSet);
                break;
+            case COMPOSITE_DO_WHILE:
+               compositeInstruction = new CompositeDoWhileInstruction(_methodModel, _firstChild, _lastChild, _branchSet);
+               break;
          }
          return (compositeInstruction);
 
@@ -886,6 +890,15 @@ class InstructionSet{
 
       }
    }
+   
+   static class CompositeDoWhileInstruction extends CompositeInstruction{
+
+      protected CompositeDoWhileInstruction(MethodModel method, Instruction _firstChild, Instruction _lastChild,
+            BranchSet _branchSet) {
+         super(method, ByteCode.COMPOSITE_DO_WHILE, _firstChild, _lastChild, _branchSet);
+
+      }
+   }
 
    static class CompositeForEclipseInstruction extends CompositeInstruction{
 
diff --git a/test/codegen/src/java/com/amd/aparapi/test/DoWhile.java b/test/codegen/src/java/com/amd/aparapi/test/DoWhile.java
new file mode 100644
index 00000000..409efbc1
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/DoWhile.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class DoWhile{
+   public void run() {
+      @SuppressWarnings("unused") boolean pass = false;
+      int i = 0;
+      do{
+         pass = true;
+         i++;
+      }while (i < 10);
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      char pass = 0;
+      int i = 0;
+      do{
+         pass = 1;
+         i++;
+      }while (i<10);
+      return;
+   }
+}
+}OpenCL}**/
-- 
GitLab