From 32fad7c5092bcb12ef88502e50601ddccbfbdc0a Mon Sep 17 00:00:00 2001
From: Gary Frost <frost.gary@gmail.com>
Date: Tue, 13 Sep 2011 22:11:13 +0000
Subject: [PATCH] Initial AMD Contribution

---
 com.amd.aparapi.jni/.project                  |   11 +
 com.amd.aparapi.jni/build.properties          |   44 +
 com.amd.aparapi.jni/build.xml                 |  295 ++
 com.amd.aparapi.jni/src/cpp/aparapi.cpp       | 1499 ++++++
 com.amd.aparapi/.classpath                    |    7 +
 com.amd.aparapi/.project                      |   17 +
 com.amd.aparapi/build.xml                     |   19 +
 com.amd.aparapi/noant.bat                     |   88 +
 .../src/java/com/amd/aparapi/Annotations.java |   86 +
 .../com/amd/aparapi/AparapiException.java     |   64 +
 .../src/java/com/amd/aparapi/BlockWriter.java |  683 +++
 .../src/java/com/amd/aparapi/BranchSet.java   |  372 ++
 .../src/java/com/amd/aparapi/ByteBuffer.java  |  225 +
 .../src/java/com/amd/aparapi/ByteReader.java  |  165 +
 .../src/java/com/amd/aparapi/ClassModel.java  | 2388 +++++++++
 .../com/amd/aparapi/ClassParseException.java  |  129 +
 .../com/amd/aparapi/CodeGenException.java     |   46 +
 .../src/java/com/amd/aparapi/Config.java      |  199 +
 .../src/java/com/amd/aparapi/Entrypoint.java  |  867 ++++
 .../java/com/amd/aparapi/ExpressionList.java  |  942 ++++
 .../src/java/com/amd/aparapi/Instruction.java |  388 ++
 .../com/amd/aparapi/InstructionPattern.java   |  507 ++
 .../java/com/amd/aparapi/InstructionSet.java  | 4273 +++++++++++++++++
 .../amd/aparapi/InstructionTransformer.java   |   52 +
 .../src/java/com/amd/aparapi/Kernel.java      | 1873 ++++++++
 .../java/com/amd/aparapi/KernelRunner.java    | 1430 ++++++
 .../java/com/amd/aparapi/KernelWriter.java    |  566 +++
 .../src/java/com/amd/aparapi/MethodModel.java | 1588 ++++++
 .../java/com/amd/aparapi/UnsafeWrapper.java   |  414 ++
 examples/effects/.classpath                   |    8 +
 examples/effects/.project                     |   17 +
 examples/effects/build.xml                    |   35 +
 .../amd/aparapi/examples/effects/Main.java    |  270 ++
 examples/nbody/.classpath                     |   11 +
 examples/nbody/.project                       |   17 +
 examples/nbody/build.xml                      |   82 +
 examples/nbody/nbody.bat                      |   19 +
 examples/nbody/nbody.sh                       |   16 +
 .../com/amd/aparapi/examples/nbody/Main.java  |  325 ++
 .../amd/aparapi/examples/nbody/particle.jpg   |  Bin 0 -> 1056 bytes
 samples/blackscholes/blackscholes.bash        |    7 +
 samples/blackscholes/blackscholes.bat         |    7 +
 samples/blackscholes/build.xml                |   20 +
 .../aparapi/samples/blackscholes/Main.java    |  203 +
 samples/mandel/.classpath                     |    8 +
 samples/mandel/.project                       |   17 +
 samples/mandel/build.xml                      |   20 +
 samples/mandel/mandel.bat                     |    9 +
 samples/mandel/mandel.sh                      |    5 +
 .../com/amd/aparapi/sample/mandel/Main.java   |  285 ++
 samples/squares/.classpath                    |    8 +
 samples/squares/.project                      |   17 +
 samples/squares/build.xml                     |   20 +
 samples/squares/squares.bat                   |    6 +
 samples/squares/squares.sh                    |    5 +
 .../com/amd/aparapi/sample/squares/Main.java  |   94 +
 test/codegen/.classpath                       |    9 +
 test/codegen/.project                         |   17 +
 test/codegen/build.xml                        |   72 +
 .../com/amd/aparapi/CodeGenJUnitBase.java     |  110 +
 .../com/amd/aparapi/CreateJUnitTests.java     |  127 +
 .../src/java/com/amd/aparapi/Diff.java        |  267 +
 .../java/com/amd/aparapi/KernelHelper.java    |   56 +
 .../src/java/com/amd/aparapi/Source.java      |  186 +
 .../src/java/com/amd/aparapi/SwingDiff.java   |  203 +
 .../amd/aparapi/test/AccessBooleanArray.java  |   44 +
 .../com/amd/aparapi/test/AccessByteArray.java |   47 +
 .../amd/aparapi/test/AccessDoubleArray.java   |   39 +
 .../amd/aparapi/test/AccessFloatArray.java    |   37 +
 .../com/amd/aparapi/test/AccessIntArray.java  |   37 +
 .../com/amd/aparapi/test/AccessLongArray.java |   37 +
 .../amd/aparapi/test/AccessShortArray.java    |   37 +
 .../amd/aparapi/test/AndOrAndPrecedence.java  |   44 +
 .../com/amd/aparapi/test/AndOrPrecedence.java |   42 +
 .../amd/aparapi/test/AndOrPrecedence2.java    |   42 +
 .../com/amd/aparapi/test/ArbitraryScope.java  |  103 +
 .../com/amd/aparapi/test/ArbitraryScope2.java |  104 +
 .../aparapi/test/ArbitraryScopeSimple.java    |   47 +
 .../test/AssignAndPassAsParameter.java        |   50 +
 .../test/AssignAndPassAsParameterSimple.java  |   14 +
 .../com/amd/aparapi/test/AssignField.java     |   10 +
 .../com/amd/aparapi/test/Atomic32Pragma.java  |   43 +
 .../com/amd/aparapi/test/BooleanToggle.java   |   50 +
 .../src/java/com/amd/aparapi/test/Break.java  |   14 +
 .../java/com/amd/aparapi/test/ByteParams.java |   45 +
 .../amd/aparapi/test/ByteParamsSimple.java    |   42 +
 .../com/amd/aparapi/test/CallGetPassId.java   |   31 +
 .../java/com/amd/aparapi/test/CallObject.java |   20 +
 .../amd/aparapi/test/CallObjectStatic.java    |   19 +
 .../com/amd/aparapi/test/CallRunSuper.java    |   47 +
 .../java/com/amd/aparapi/test/CallSuper.java  |   50 +
 .../java/com/amd/aparapi/test/CallTwice.java  |   42 +
 .../com/amd/aparapi/test/CharArrayField.java  |   13 +
 .../com/amd/aparapi/test/CharAsParameter.java |   21 +
 .../java/com/amd/aparapi/test/CharType.java   |   14 +
 .../test/ClassHasStaticFieldAccess.java       |   16 +
 .../aparapi/test/ClassHasStaticMethod.java    |   22 +
 .../test/ClassHasStaticMethodSimple.java      |   14 +
 .../aparapi/test/CompositeArbitraryScope.java |  183 +
 .../test/ConstantAssignInExpression.java      |   39 +
 .../java/com/amd/aparapi/test/Continue.java   |   40 +
 .../com/amd/aparapi/test/ContinueTorture.java |   38 +
 .../com/amd/aparapi/test/DirectRecursion.java |   19 +
 .../src/java/com/amd/aparapi/test/Drem.java   |   45 +
 .../amd/aparapi/test/EmptyWhileWithInc.java   |   28 +
 .../amd/aparapi/test/EntrypointRecursion.java |   20 +
 .../src/java/com/amd/aparapi/test/Ex.java     |   37 +
 .../aparapi/test/FirstAssignInExpression.java |   42 +
 .../test/FirstAssignInExpression2.java        |   48 +
 .../com/amd/aparapi/test/FloatParams.java     |   44 +
 .../amd/aparapi/test/FloatParamsSimple.java   |   38 +
 .../src/java/com/amd/aparapi/test/For.java    |   33 +
 .../src/java/com/amd/aparapi/test/ForAnd.java |   35 +
 .../com/amd/aparapi/test/ForAndMandel.java    |   87 +
 .../test/ForAndMandelNoInitialize.java        |   88 +
 .../java/com/amd/aparapi/test/ForAsFirst.java |   33 +
 .../amd/aparapi/test/ForBooleanToggle.java    |   60 +
 .../java/com/amd/aparapi/test/ForBreak.java   |   18 +
 .../java/com/amd/aparapi/test/ForEach.java    |   18 +
 .../src/java/com/amd/aparapi/test/ForIf.java  |   39 +
 .../com/amd/aparapi/test/ForIfMandel.java     |   94 +
 .../src/java/com/amd/aparapi/test/Frem.java   |   42 +
 .../amd/aparapi/test/IEEERemainderDouble.java |   47 +
 .../amd/aparapi/test/IEEERemainderFloat.java  |   45 +
 .../src/java/com/amd/aparapi/test/If.java     |   38 +
 .../src/java/com/amd/aparapi/test/IfAnd.java  |   38 +
 .../java/com/amd/aparapi/test/IfAndAnd.java   |   38 +
 .../com/amd/aparapi/test/IfAndAndAnd.java     |   38 +
 .../java/com/amd/aparapi/test/IfAndOrAnd.java |   38 +
 .../amd/aparapi/test/IfBooleanAndAndAnd.java  |   41 +
 .../amd/aparapi/test/IfBooleanAndAndOr.java   |   41 +
 .../amd/aparapi/test/IfBooleanAndOrAnd.java   |   41 +
 .../amd/aparapi/test/IfBooleanAndOrOr.java    |   41 +
 .../amd/aparapi/test/IfBooleanOrAndAnd.java   |   41 +
 .../amd/aparapi/test/IfBooleanOrAndOr.java    |   44 +
 .../amd/aparapi/test/IfBooleanOrOrAnd.java    |   41 +
 .../com/amd/aparapi/test/IfBooleanOrOrOr.java |   41 +
 .../src/java/com/amd/aparapi/test/IfElse.java |   42 +
 .../java/com/amd/aparapi/test/IfElseAnd.java  |   42 +
 .../com/amd/aparapi/test/IfElseAndAndAnd.java |   42 +
 .../amd/aparapi/test/IfElseIfElseIfElse.java  |  105 +
 .../aparapi/test/IfElseNot__OrOr_And_.java    |   42 +
 .../com/amd/aparapi/test/IfElseOrOrAnd.java   |   42 +
 .../com/amd/aparapi/test/IfElseOrOrOr.java    |   42 +
 .../amd/aparapi/test/IfElse_And_Or_And.java   |   45 +
 .../com/amd/aparapi/test/IfElse_OrOr_And.java |   42 +
 .../amd/aparapi/test/IfElse_Or_And_Or.java    |   45 +
 .../src/java/com/amd/aparapi/test/IfOr.java   |   38 +
 .../java/com/amd/aparapi/test/IfOrAndOr.java  |   38 +
 .../src/java/com/amd/aparapi/test/IfOrOr.java |   38 +
 .../java/com/amd/aparapi/test/IfOrOrAnd.java  |   38 +
 .../java/com/amd/aparapi/test/IfOrOrOr.java   |   38 +
 .../test/If_IfElseIfElseElse_Else.java        |   60 +
 .../com/amd/aparapi/test/If_IfElse_Else.java  |   52 +
 .../aparapi/test/If_IfElse_Else_IfElse_.java  |  126 +
 .../java/com/amd/aparapi/test/If_If_Else.java |   59 +
 .../com/amd/aparapi/test/If_If_Else2.java     |   44 +
 .../com/amd/aparapi/test/If_If_Else_If_.java  |   64 +
 .../com/amd/aparapi/test/If_OrOr_And.java     |   38 +
 .../com/amd/aparapi/test/If_While_Else.java   |   44 +
 .../amd/aparapi/test/If_While_Else_While.java |   46 +
 .../amd/aparapi/test/ImplementsInterface.java |   52 +
 .../amd/aparapi/test/IncArrayArgContent.java  |   43 +
 .../java/com/amd/aparapi/test/IncField.java   |   10 +
 .../amd/aparapi/test/IndirectRecursion.java   |   26 +
 .../java/com/amd/aparapi/test/Interface.java  |   23 +
 .../com/amd/aparapi/test/LongCompare.java     |   40 +
 .../com/amd/aparapi/test/LongCompares.java    |   38 +
 .../src/java/com/amd/aparapi/test/Loops.java  |   41 +
 .../java/com/amd/aparapi/test/MathAbs.java    |   45 +
 .../java/com/amd/aparapi/test/MathDegRad.java |   41 +
 .../com/amd/aparapi/test/MathFallThru.java    |   51 +
 .../java/com/amd/aparapi/test/MathMax.java    |   50 +
 .../java/com/amd/aparapi/test/MathMin.java    |   50 +
 .../com/amd/aparapi/test/MathRemainder.java   |   43 +
 .../com/amd/aparapi/test/MultiContinue.java   |   59 +
 .../com/amd/aparapi/test/MultipleAssign.java  |   36 +
 .../amd/aparapi/test/MultipleAssignExpr.java  |   43 +
 .../com/amd/aparapi/test/NewLocalArray.java   |   39 +
 .../test/ObjectArrayCallHierarchy.java        |   68 +
 .../aparapi/test/ObjectArrayCommonSuper.java  |   53 +
 .../aparapi/test/ObjectArrayMemberAccess.java |   95 +
 .../test/ObjectArrayMemberBadGetter.java      |   40 +
 .../test/ObjectArrayMemberBadSetter.java      |   39 +
 .../aparapi/test/ObjectArrayMemberCall.java   |  108 +
 .../test/ObjectArrayMemberGetterSetter.java   |  223 +
 .../test/ObjectArrayMemberHierarchy.java      |  111 +
 .../test/ObjectArrayMemberNotFinal.java       |   91 +
 .../com/amd/aparapi/test/ObjectRefCopy.java   |   23 +
 .../amd/aparapi/test/ObjectWithinObject.java  |   26 +
 .../amd/aparapi/test/OrAndOrPrecedence.java   |   44 +
 .../com/amd/aparapi/test/OverloadMethod.java  |   47 +
 .../aparapi/test/OverriddenKernelField.java   |   57 +
 .../java/com/amd/aparapi/test/PlayPen.java    |   58 +
 .../amd/aparapi/test/PostDecArrayItem.java    |   46 +
 .../com/amd/aparapi/test/PostDecByte.java     |   41 +
 .../com/amd/aparapi/test/PostDecLocal.java    |   37 +
 .../com/amd/aparapi/test/PostDecPostInc.java  |   34 +
 .../test/PostIncArrayIndexAndElement.java     |   35 +
 .../amd/aparapi/test/PostIncArrayItem.java    |   46 +
 .../test/PostIncArrayItemAsParameter.java     |   49 +
 .../test/PostIncArrayItemFieldIndex.java      |   45 +
 .../com/amd/aparapi/test/PostIncByte.java     |   42 +
 .../amd/aparapi/test/PostIncByteField.java    |   17 +
 .../java/com/amd/aparapi/test/PostIncInt.java |   39 +
 .../com/amd/aparapi/test/PostIncIntField.java |   17 +
 .../com/amd/aparapi/test/PostIncLocal.java    |   37 +
 .../aparapi/test/PostIncLocalStandalone.java  |   33 +
 .../amd/aparapi/test/PostIncLocalTwice.java   |   37 +
 .../test/PreDecArrayIndexAndElement.java      |   35 +
 .../com/amd/aparapi/test/PreDecArrayItem.java |   43 +
 .../com/amd/aparapi/test/PreDecPostInc.java   |   35 +
 .../test/PreIncArrayIndexAndElement.java      |   35 +
 .../com/amd/aparapi/test/PreIncArrayItem.java |   43 +
 .../java/com/amd/aparapi/test/PreIncByte.java |   61 +
 .../com/amd/aparapi/test/PreIncByteField.java |   17 +
 .../java/com/amd/aparapi/test/PreIncInt.java  |   41 +
 .../com/amd/aparapi/test/PreIncIntField.java  |   17 +
 .../com/amd/aparapi/test/PreIncLocal.java     |   38 +
 .../aparapi/test/PreIncLocalStandalone.java   |   33 +
 .../amd/aparapi/test/PreIncLocalTwice.java    |   38 +
 .../aparapi/test/ReturnBooleanNewArray.java   |   14 +
 .../aparapi/test/ReturnBooleanVarArray.java   |   16 +
 .../amd/aparapi/test/ReturnByteArrayNew.java  |   13 +
 .../amd/aparapi/test/ReturnByteArrayVar.java  |   15 +
 .../aparapi/test/ReturnDoubleArrayNew.java    |   13 +
 .../aparapi/test/ReturnDoubleArrayVar.java    |   15 +
 .../amd/aparapi/test/ReturnFloatArrayNew.java |   13 +
 .../amd/aparapi/test/ReturnFloatArrayVar.java |   15 +
 .../amd/aparapi/test/ReturnIntArrayNew.java   |   13 +
 .../amd/aparapi/test/ReturnIntArrayVar.java   |   15 +
 .../amd/aparapi/test/ReturnLongArrayNew.java  |   13 +
 .../amd/aparapi/test/ReturnLongArrayVar.java  |   15 +
 .../amd/aparapi/test/ReturnPostIncInt.java    |   35 +
 .../com/amd/aparapi/test/ReturnPreIncInt.java |   36 +
 .../amd/aparapi/test/ReturnShortArrayNew.java |   13 +
 .../amd/aparapi/test/ReturnShortArrayVar.java |   15 +
 .../com/amd/aparapi/test/RightShifts.java     |   46 +
 .../java/com/amd/aparapi/test/Sequence.java   |   27 +
 .../amd/aparapi/test/StaticFieldStore.java    |   12 +
 .../amd/aparapi/test/SynchronizedMethods.java |   27 +
 .../java/com/amd/aparapi/test/Ternary.java    |   37 +
 .../java/com/amd/aparapi/test/TernaryAnd.java |   35 +
 .../com/amd/aparapi/test/TernaryAndOr.java    |   34 +
 .../com/amd/aparapi/test/TernaryNested.java   |   31 +
 .../java/com/amd/aparapi/test/TernaryOr.java  |   36 +
 .../com/amd/aparapi/test/TwoForLoops.java     |   50 +
 .../UnrelatedIfElsesWithCommonEndByte.java    |   84 +
 .../test/UnrelatedIfsWithCommonEndByte.java   |   67 +
 .../aparapi/test/UnrelatedNestedIfElses.java  |   70 +
 .../java/com/amd/aparapi/test/UseObject.java  |   22 +
 .../aparapi/test/UseObjectArrayLength.java    |   46 +
 .../com/amd/aparapi/test/UsesArrayLength.java |  130 +
 .../java/com/amd/aparapi/test/UsesNew.java    |   12 +
 .../java/com/amd/aparapi/test/UsesThrow.java  |   26 +
 .../com/amd/aparapi/test/VarargsForEach.java  |   24 +
 .../com/amd/aparapi/test/VarargsSimple.java   |   24 +
 .../src/java/com/amd/aparapi/test/While.java  |   38 +
 .../com/amd/aparapi/test/WhileAndMandel.java  |   90 +
 .../com/amd/aparapi/test/WhileEmptyLoop.java  |   30 +
 .../java/com/amd/aparapi/test/WhileIf.java    |   46 +
 .../com/amd/aparapi/test/WhileIfElse.java     |   49 +
 .../amd/aparapi/test/WhileWithoutMutator.java |   30 +
 .../amd/aparapi/test/While_If_IfElseElse.java |  116 +
 264 files changed, 30357 insertions(+)
 create mode 100644 com.amd.aparapi.jni/.project
 create mode 100644 com.amd.aparapi.jni/build.properties
 create mode 100644 com.amd.aparapi.jni/build.xml
 create mode 100644 com.amd.aparapi.jni/src/cpp/aparapi.cpp
 create mode 100644 com.amd.aparapi/.classpath
 create mode 100644 com.amd.aparapi/.project
 create mode 100644 com.amd.aparapi/build.xml
 create mode 100644 com.amd.aparapi/noant.bat
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/Annotations.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/AparapiException.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/BlockWriter.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/BranchSet.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/ByteBuffer.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/ByteReader.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/ClassModel.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/ClassParseException.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/CodeGenException.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/Config.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/Entrypoint.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/ExpressionList.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/Instruction.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/InstructionPattern.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/InstructionSet.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/InstructionTransformer.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/Kernel.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/KernelRunner.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/KernelWriter.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/MethodModel.java
 create mode 100644 com.amd.aparapi/src/java/com/amd/aparapi/UnsafeWrapper.java
 create mode 100644 examples/effects/.classpath
 create mode 100644 examples/effects/.project
 create mode 100644 examples/effects/build.xml
 create mode 100644 examples/effects/src/com/amd/aparapi/examples/effects/Main.java
 create mode 100644 examples/nbody/.classpath
 create mode 100644 examples/nbody/.project
 create mode 100644 examples/nbody/build.xml
 create mode 100644 examples/nbody/nbody.bat
 create mode 100644 examples/nbody/nbody.sh
 create mode 100644 examples/nbody/src/com/amd/aparapi/examples/nbody/Main.java
 create mode 100644 examples/nbody/src/com/amd/aparapi/examples/nbody/particle.jpg
 create mode 100644 samples/blackscholes/blackscholes.bash
 create mode 100644 samples/blackscholes/blackscholes.bat
 create mode 100644 samples/blackscholes/build.xml
 create mode 100644 samples/blackscholes/src/com/amd/aparapi/samples/blackscholes/Main.java
 create mode 100644 samples/mandel/.classpath
 create mode 100644 samples/mandel/.project
 create mode 100644 samples/mandel/build.xml
 create mode 100644 samples/mandel/mandel.bat
 create mode 100644 samples/mandel/mandel.sh
 create mode 100644 samples/mandel/src/com/amd/aparapi/sample/mandel/Main.java
 create mode 100644 samples/squares/.classpath
 create mode 100644 samples/squares/.project
 create mode 100644 samples/squares/build.xml
 create mode 100644 samples/squares/squares.bat
 create mode 100644 samples/squares/squares.sh
 create mode 100644 samples/squares/src/com/amd/aparapi/sample/squares/Main.java
 create mode 100644 test/codegen/.classpath
 create mode 100644 test/codegen/.project
 create mode 100644 test/codegen/build.xml
 create mode 100644 test/codegen/src/java/com/amd/aparapi/CodeGenJUnitBase.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/CreateJUnitTests.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/Diff.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/KernelHelper.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/Source.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/SwingDiff.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/AccessBooleanArray.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/AccessByteArray.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/AccessDoubleArray.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/AccessFloatArray.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/AccessIntArray.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/AccessLongArray.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/AccessShortArray.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/AndOrAndPrecedence.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/AndOrPrecedence.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/AndOrPrecedence2.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ArbitraryScope.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ArbitraryScope2.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ArbitraryScopeSimple.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/AssignAndPassAsParameter.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/AssignAndPassAsParameterSimple.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/AssignField.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/Atomic32Pragma.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/BooleanToggle.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/Break.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ByteParams.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ByteParamsSimple.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/CallGetPassId.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/CallObject.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/CallObjectStatic.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/CallRunSuper.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/CallSuper.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/CallTwice.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/CharArrayField.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/CharAsParameter.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/CharType.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ClassHasStaticFieldAccess.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ClassHasStaticMethod.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ClassHasStaticMethodSimple.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/CompositeArbitraryScope.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ConstantAssignInExpression.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/Continue.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ContinueTorture.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/DirectRecursion.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/Drem.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/EmptyWhileWithInc.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/EntrypointRecursion.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/Ex.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/FirstAssignInExpression.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/FirstAssignInExpression2.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/FloatParams.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/FloatParamsSimple.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/For.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ForAnd.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ForAndMandel.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ForAndMandelNoInitialize.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ForAsFirst.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ForBooleanToggle.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ForBreak.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ForEach.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ForIf.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ForIfMandel.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/Frem.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IEEERemainderDouble.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IEEERemainderFloat.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/If.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfAnd.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfAndAnd.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfAndAndAnd.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfAndOrAnd.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfBooleanAndAndAnd.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfBooleanAndAndOr.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfBooleanAndOrAnd.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfBooleanAndOrOr.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfBooleanOrAndAnd.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfBooleanOrAndOr.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfBooleanOrOrAnd.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfBooleanOrOrOr.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfElse.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfElseAnd.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfElseAndAndAnd.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfElseIfElseIfElse.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfElseNot__OrOr_And_.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfElseOrOrAnd.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfElseOrOrOr.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfElse_And_Or_And.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfElse_OrOr_And.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfElse_Or_And_Or.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfOr.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfOrAndOr.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfOrOr.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfOrOrAnd.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IfOrOrOr.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/If_IfElseIfElseElse_Else.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/If_IfElse_Else.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/If_IfElse_Else_IfElse_.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/If_If_Else.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/If_If_Else2.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/If_If_Else_If_.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/If_OrOr_And.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/If_While_Else.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/If_While_Else_While.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ImplementsInterface.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IncArrayArgContent.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IncField.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/IndirectRecursion.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/Interface.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/LongCompare.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/LongCompares.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/Loops.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/MathAbs.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/MathDegRad.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/MathFallThru.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/MathMax.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/MathMin.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/MathRemainder.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/MultiContinue.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/MultipleAssign.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/MultipleAssignExpr.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/NewLocalArray.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ObjectArrayCallHierarchy.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ObjectArrayCommonSuper.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberAccess.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberBadGetter.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberBadSetter.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberCall.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberGetterSetter.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberHierarchy.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberNotFinal.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ObjectRefCopy.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ObjectWithinObject.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/OrAndOrPrecedence.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/OverloadMethod.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/OverriddenKernelField.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PlayPen.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PostDecArrayItem.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PostDecByte.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PostDecLocal.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PostDecPostInc.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PostIncArrayIndexAndElement.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PostIncArrayItem.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PostIncArrayItemAsParameter.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PostIncArrayItemFieldIndex.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PostIncByte.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PostIncByteField.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PostIncInt.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PostIncIntField.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PostIncLocal.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PostIncLocalStandalone.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PostIncLocalTwice.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PreDecArrayIndexAndElement.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PreDecArrayItem.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PreDecPostInc.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PreIncArrayIndexAndElement.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PreIncArrayItem.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PreIncByte.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PreIncByteField.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PreIncInt.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PreIncIntField.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PreIncLocal.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PreIncLocalStandalone.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/PreIncLocalTwice.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ReturnBooleanNewArray.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ReturnBooleanVarArray.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ReturnByteArrayNew.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ReturnByteArrayVar.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ReturnDoubleArrayNew.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ReturnDoubleArrayVar.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ReturnFloatArrayNew.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ReturnFloatArrayVar.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ReturnIntArrayNew.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ReturnIntArrayVar.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ReturnLongArrayNew.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ReturnLongArrayVar.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ReturnPostIncInt.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ReturnPreIncInt.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ReturnShortArrayNew.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/ReturnShortArrayVar.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/RightShifts.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/Sequence.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/StaticFieldStore.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/SynchronizedMethods.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/Ternary.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/TernaryAnd.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/TernaryAndOr.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/TernaryNested.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/TernaryOr.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/TwoForLoops.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/UnrelatedIfElsesWithCommonEndByte.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/UnrelatedIfsWithCommonEndByte.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/UnrelatedNestedIfElses.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/UseObject.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/UseObjectArrayLength.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/UsesArrayLength.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/UsesNew.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/UsesThrow.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/VarargsForEach.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/VarargsSimple.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/While.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/WhileAndMandel.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/WhileEmptyLoop.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/WhileIf.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/WhileIfElse.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/WhileWithoutMutator.java
 create mode 100644 test/codegen/src/java/com/amd/aparapi/test/While_If_IfElseElse.java

diff --git a/com.amd.aparapi.jni/.project b/com.amd.aparapi.jni/.project
new file mode 100644
index 00000000..03483fdc
--- /dev/null
+++ b/com.amd.aparapi.jni/.project
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>com.amd.aparapi.jni</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+	</buildSpec>
+	<natures>
+	</natures>
+</projectDescription>
diff --git a/com.amd.aparapi.jni/build.properties b/com.amd.aparapi.jni/build.properties
new file mode 100644
index 00000000..fe1ae736
--- /dev/null
+++ b/com.amd.aparapi.jni/build.properties
@@ -0,0 +1,44 @@
+
+###amd.app.dir{
+#
+# Set this to the location where the AMD APP SDK is installed.
+# JNI compile process needs this so we can locate the OpenCL libraries and headers 
+# 
+# Usually "C:\\Program Files\\AMD APP" if you took installer defaults when installing "AMD APP SDK" on 32 bit Windows
+amd.app.sdk.dir=C:\\Program Files\\AMD APP
+#
+# Or "C:\\Program Files (x86)\\AMD APP" if you took installer defaults when installing "AMD APP SDK" on 64 bit Windows
+#amd.app.sdk.dir=C:\\Program Files (x86)\\AMD APP
+#
+# Will need to be set to wherever you install the SDK on Linux
+#amd.app.sdk.dir=/home/gfrost/opencl/ati-stream-sdk-v2.3-lnx64
+#amd.app.sdk.dir=/opt/AMDAPP
+#
+###amd.app.dir}
+###Windows{
+#
+# We need to set up either visual studio or MinGW compiler info
+#
+###Windows Visual Studio{
+# We need to know where Visual Studio is installed
+msvc.dir=C:\\Program Files\\Microsoft Visual Studio 9.0
+#msvc.dir=C:\\Program Files\\Microsoft Visual Studio 10.0
+#
+#msvc.dir=C:\\Program Files (x86)\\Microsoft Visual Studio 9.0
+#
+# We need to know where the microsoft SDK was installed so we can configure include and lib paths
+#msvc.sdk.dir=C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0a
+msvc.sdk.dir=C:\\Program Files\\Microsoft SDKs\\Windows\\v6.0A
+#
+###Windows Visual Studio}
+
+###Windows MinGW{
+#
+# MinGW is simpler ;) we just need the install dir. At runtime you will need ${mingw.dir}/bin in your path!
+#mingw.dir=c:\\MinGW
+#
+#mingw.dir=c:\\devel\\MinGW
+#
+###Windows MinGW}
+
+###Windows}
diff --git a/com.amd.aparapi.jni/build.xml b/com.amd.aparapi.jni/build.xml
new file mode 100644
index 00000000..a50be433
--- /dev/null
+++ b/com.amd.aparapi.jni/build.xml
@@ -0,0 +1,295 @@
+<?xml version="1.0"?>
+
+
+<!--
+You should not have to edit this file. First consider editing the properties in build.properties.
+-->
+
+<project name="com.amd.aparapi.jni" default="build" basedir=".">
+   <property environment="env" />   <!-- we need env.PATH for msvc only -->
+   <property file="build.properties"/>
+
+   <target name="check">
+      <fail message="Error:">
+         <condition>
+            <and>
+               <os family="windows" />
+               <isset property="msvc.dir"/>
+               <not><isset property="msvc.sdk.dir"/></not>
+            </and>
+         </condition>
+         <![CDATA[
+         You will need to edit com.amd.aparapi.jni/build.properties to compile aparapi JNI code
+
+         At present msvc.dir seems to be configured but not msvc.sdk.dir
+         ]]>
+      </fail>
+
+      <fail message="Error:">
+         <condition>
+            <and>
+               <os family="windows" />
+               <not><isset property="msvc.dir"/></not>
+               <isset property="msvc.sdk.dir"/>
+            </and>
+         </condition>
+         <![CDATA[
+         You will need to edit com.amd.aparapi.jni/build.properties to compile aparapi JNI code
+
+         At present msvc.sdk.dir seems to be configured but not msvc.dir
+         ]]>
+      </fail>
+      <available file="${msvc.dir}" type="dir" property="msvc.dir.exists"/>
+      <available file="${msvc.sdk.dir}" type="dir" property="msvc.sdk.dir.exists"/>
+
+      <fail message="Error:">
+         <condition>
+            <and>
+               <os family="windows" />
+               <isset property="msvc.dir"/>
+               <not><isset property="msvc.dir.exists"/></not>
+            </and>
+         </condition>
+         <![CDATA[
+         You will need to edit com.amd.aparapi.jni/build.properties to compile aparapi JNI code
+
+         At present msvc.dir is set (to ${msvc.dir}) but that dir does not exist
+         ]]>
+      </fail>
+      <fail message="Error:">
+         <condition>
+            <and>
+               <os family="windows" />
+               <isset property="msvc.sdk.dir"/>
+               <not><isset property="msvc.sdk.dir.exists"/></not>
+            </and>
+         </condition>
+         <![CDATA[
+         You will need to edit com.amd.aparapi.jni/build.properties to compile aparapi JNI code
+
+         At present msvc.sdk.dir is set (to ${msvc.sdk.dir}) but that dir does not exist
+         ]]>
+      </fail>
+
+
+      <available file="${mingw.dir}" type="dir" property="mingw.dir.exists"/>
+      <fail message="Error:">
+         <condition>
+            <and>
+               <os family="windows" />
+               <isset property="mingw.dir"/>
+               <not><isset property="mingw.dir.exists"/></not>
+            </and>
+         </condition>
+         <![CDATA[
+         You will need to edit com.amd.aparapi.jni/build.properties to compile aparapi JNI code
+
+         At present mingw.dir is set (to ${mingw.dir}) but that dir does not exist
+         ]]>
+      </fail>
+      <!--<echo message="java.home ${java.home}"/>-->
+      <!--<echo message="msvc.dir.exists ${msvc.dir.exists}"/>-->
+      <!--<echo message="msvc.sdk.dir.exists ${msvc.sdk.dir.exists}"/>-->
+      <!--<echo message="mingw.dir.exists ${mingw.dir.exists}"/>-->
+      <condition property="use.msvc"> 
+         <and>
+            <os family="windows" />
+            <isset property="msvc.dir.exists"/>
+            <isset property="msvc.sdk.dir.exists"/>
+         </and>
+      </condition>
+      <!--<echo message="use.msvc ${use.msvc}"/>-->
+
+      <condition property="use.mingw"> 
+         <and>
+            <os family="windows" />
+            <isset property="mingw.dir.exists"/>
+         </and>
+      </condition>
+      <!--<echo message="use.mingw ${use.mingw}"/>-->
+
+      <fail message="Error:">
+         <condition>
+            <and>
+               <isset property="use.mingw"/>
+               <isset property="use.msvc"/>
+            </and>
+         </condition>
+         <![CDATA[
+         You will need to edit com.amd.aparapi.jni/build.properties to compile aparapi JNI code
+
+         At present ant is configured for both MinGW AND Microsoft Visual Studio. You need to pick one or the other :) !
+
+         Just comment out the properties for the compiler that you *do not* wish to use.
+         ]]>
+      </fail>
+
+      <fail message="Error:">
+         <condition>
+            <and>
+               <os family="windows" />
+               <not>
+                  <or>
+                     <isset property="use.mingw"/>
+                     <isset property="use.msvc"/>
+                  </or>
+               </not>
+            </and>
+         </condition>
+         <![CDATA[
+         You will need to edit com.amd.aparapi.jni/build.properties to compile aparapi JNI code
+
+         This looks like a windows machine so you probably need to configure either:-
+
+         * msvc.dir and msvc.sdk.dir if you wish to use Microsoft Visual Studio compiler
+
+         * mingw.dir if you prefer if you prefer to use MinGW 
+         ]]>
+      </fail>
+      <condition property="use.gcc"> <os family="unix" /> </condition>
+
+      <condition property="x86_or_x86_64" value="x86" else="x86_64"> <or><os arch="x86"/><os arch="i386"/></or> </condition>
+
+      <condition property="optional.amd64.subdir" value="" else="amd64\"> <or><os arch="x86"/><os arch="i386"/></or> </condition>
+
+      <condition property="optional.x64.subdir" value="" else="x64\"> <or><os arch="x86"/><os arch="i386"/></or></condition>
+
+      <property name="cl" value="${msvc.dir}\vc\bin\${optional.amd64.subdir}cl.exe"/>
+
+      <available file="${msvc.dir}\vc\bin\${optional.amd64.subdir}cl.exe" type="file" property="cl.exists"/>
+
+      <fail message="Error:">
+         <condition>
+            <and>
+               <isset property="use.msvc"/>
+               <not><isset property="cl.exists"/></not>
+            </and>
+         </condition>
+         <![CDATA[
+         You will need to edit com.amd.aparapi.jni/build.properties to compile aparapi JNI code
+
+         Could not find vc\bin\${optional.amd64.subdir}cl under configured msvc.dir. Check if msvc.dir is pointing
+         to a valid visual studio installation
+         ]]>
+      </fail>
+
+      <fail message="Error:">
+         <condition>
+            <not><isset property="amd.app.sdk.dir"/></not>
+         </condition>
+         <![CDATA[
+         You will need to edit com.amd.aparapi.jni/build.properties to compile aparapi JNI code
+
+         You need to set amd.app.sdk.dir to point to the location where AMD APP SDK is installed
+         ]]>
+      </fail>
+      <available file="${amd.app.sdk.dir}" type="dir" property="amd.app.sdk.dir.exists"/>
+
+      <fail message="Error:">
+         <condition>
+            <not><isset property="amd.app.sdk.dir.exists"/></not>
+         </condition>
+         <![CDATA[
+         You will need to edit com.amd.aparapi.jni/build.properties to compile aparapi JNI code
+
+         At present amd.app.sdk.dir is set (to ${amd.app.sdk.dir}) but that dir does not exist
+         ]]>
+      </fail>
+
+   </target>
+
+
+
+   <target name="clean" depends="check">
+      <delete dir="include"/>
+      <echo message="should remove libaparapi_${x86_or_x86_64}.so"/>
+      <delete file="libaparapi_${x86_or_x86_64}.so"/>
+      <delete file="aparapi_${x86_or_x86_64}.dll"/>
+      <delete file="aparapi.dll"/>
+      <delete file="aparapi.obj"/>
+      <delete file="aparapi.o"/>
+      <delete file="aparapi.lib"/>
+      <delete file="aparapi.exp"/>
+   </target>
+
+
+
+   <target name="javah">
+      <mkdir dir="include"/>
+      <javah classpath="..\com.amd.aparapi\aparapi.jar" destdir="include" force="true">
+         <class name="com.amd.aparapi.KernelRunner"/>
+      </javah>
+   </target>
+
+   <target name="gcc" if="use.gcc">
+      <echo message="linuxcc ${os.arch}"/>
+      <exec executable="g++" >
+         <arg value="-O3"/>
+         <arg value="-g"/>
+         <arg value="-fPIC"/>
+         <arg value="-I${java.home}/../include"/> 
+         <arg value="-I${java.home}/../include/linux"/> 
+         <arg value="-Iinclude"/> 
+         <arg value="-I${amd.app.sdk.dir}/include"/> 
+         <arg value="-shared"/>
+         <arg value="-o"/>
+         <arg value="libaparapi_${x86_or_x86_64}.so"/>
+         <arg value="src/cpp/aparapi.cpp"/>
+         <arg value="-L${amd.app.sdk.dir}/lib/${x86_or_x86_64}"/>
+         <arg value="-lOpenCL"/>
+      </exec>
+   </target>
+
+   <target name="msvc" if="use.msvc">
+
+      <exec executable="${cl}" >
+         <env key="PATH" path="${env.PATH};${msvc.dir}\\Common7\\IDE"/>
+         <arg value="/nologo"/>
+         <arg value="/TP"/>
+         <arg value="/Ox"/>
+         <arg value="/I${msvc.dir}\vc\include"/>
+         <arg value="/I${msvc.sdk.dir}\include"/>
+         <arg value="/I${java.home}\..\include"/>
+         <arg value="/I${java.home}\..\include\win32"/> 
+         <arg value="/Iinclude"/>
+         <arg value="/I${amd.app.sdk.dir}\include"/>
+         <arg value="/c"/>
+         <arg value="src\cpp\aparapi.cpp"/>
+      </exec>
+      <exec executable="${cl}" >
+         <env key="PATH" path="${env.PATH};${msvc.dir}\\Common7\\IDE"/>
+         <arg value="/nologo"/>
+         <arg value="/LD"/>
+         <arg value="aparapi.obj"/>
+         <arg value="/link"/>
+         <arg value="/libpath:${msvc.dir}\vc\lib\${optional.amd64.subdir}"/>
+         <arg value="/libpath:${msvc.sdk.dir}\lib\${optional.x64.subdir}"/>
+         <arg value="/libpath:${amd.app.sdk.dir}\lib\${x86_or_x86_64}"/>
+         <arg value="OpenCL.lib"/>
+         <arg value="/out:aparapi_${x86_or_x86_64}.dll"/>
+      </exec>
+
+   </target>
+
+   <target name="mingw" if="use.mingw">
+      <exec executable="${mingw.dir}/bin/g++" >
+         <env key="PATH" path="${env.PATH};${mingw.dir}/bin"/>
+         <arg value="-Wall"/>
+         <arg value="-O3"/>
+         <arg value="-Wl,--kill-at"/>
+         <arg value="-I${java.home}\..\include"/>
+         <arg value="-I${java.home}\..\include\win32"/>
+         <arg value="-Iinclude"/>
+         <arg value="-I${amd.app.sdk.dir}\include"/>
+         <arg value="-shared"/>
+         <arg value="-o"/>
+         <arg value="aparapi_${x86_or_x86_64}.dll"/>
+         <arg value="src\cpp\aparapi.cpp"/>
+         <arg value="-L${amd.app.sdk.dir}\lib\${x86_or_x86_64}"/>
+         <arg value="-lOpenCL"/>
+      </exec>
+   </target>
+
+   <target name="build" depends="check, javah, msvc, mingw, gcc"/>
+
+</project>
diff --git a/com.amd.aparapi.jni/src/cpp/aparapi.cpp b/com.amd.aparapi.jni/src/cpp/aparapi.cpp
new file mode 100644
index 00000000..ed0e5cc6
--- /dev/null
+++ b/com.amd.aparapi.jni/src/cpp/aparapi.cpp
@@ -0,0 +1,1499 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security’s website at http://www.bis.doc.gov/. 
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <malloc.h>
+#include <sys/types.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+#include <CL/cl.h>
+#include <jni.h>
+
+#define JNIExceptionChecker(){\
+   fprintf(stderr, "line %d\n", __LINE__);\
+   if ((jenv)->ExceptionOccurred()) {\
+      (jenv)->ExceptionDescribe(); /* write to console */\
+      (jenv)->ExceptionClear();\
+   }\
+}
+
+
+#if defined (_WIN32)
+#include "windows.h"
+#define alignedMalloc(size, alignment)\
+   _aligned_malloc(size, alignment)
+#else
+#define alignedMalloc(size, alignment)\
+   memalign(alignment, size)
+#endif
+
+
+class MicrosecondTimer{
+
+#if defined (_WIN32)
+   private:
+      __int64 freq;
+      __int64 startValue;
+   public:
+      void start(){
+         QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
+         QueryPerformanceCounter((LARGE_INTEGER*)&startValue);
+      }
+      void end(char *msg){
+         __int64 endValue;
+         QueryPerformanceCounter((LARGE_INTEGER*)&endValue);
+         int us = (int)((endValue-startValue)* 1000000.0 / freq);
+         fprintf(stderr, "%s=%d\n", msg, us);
+      }
+
+#else
+   public:
+      void start(){
+      }
+      void end(char *msg){
+      }
+
+#endif
+};
+
+MicrosecondTimer timer;
+
+
+#include "com_amd_aparapi_KernelRunner.h"
+
+#define CHECK(condition, msg) if(condition){\
+   fprintf(stderr, "!!!!!!! %s failed !!!!!!!\n", msg);\
+   return 0;\
+}
+
+
+#define ASSERT_CL_NO_RETURN(msg) if (status != CL_SUCCESS){\
+   fprintf(stderr, "!!!!!!! %s failed: %s\n", msg, CLErrString(status));\
+}
+
+#define ASSERT_CL(msg) if (status != CL_SUCCESS){\
+   ASSERT_CL_NO_RETURN(msg)\
+   return 0;\
+}
+
+#define PRINT_CL_ERR(status, msg) fprintf(stderr, "!!!!!!! %s failed %s\n", msg, CLErrString(status));
+
+#define ASSERT_FIELD(id) CHECK(id##FieldID == 0, "No such field as " #id)
+
+#define GET_DEV_INFO(deviceId, param, val, format){\
+   status = clGetDeviceInfo(deviceId, param, sizeof(val), &(val), NULL);\
+   ASSERT_CL_NO_RETURN( "clGetDeviceInfo().");\
+   /*fprintf(stderr, #param " " format " \n", val);*/ \
+}
+
+
+jfieldID typeFieldID;
+jfieldID nameFieldID;
+jfieldID javaArrayFieldID;
+jfieldID bytesPerLocalSizeFieldID;
+jfieldID sizeInBytesFieldID;
+jfieldID numElementsFieldID;
+
+// we rely on these being 0 initially to detect whether we have cached the above fieldId's 
+jclass clazz = (jclass)0;
+jclass argClazz = (jclass)0;
+
+static const char *CLErrString(cl_int status) {
+   static struct { cl_int code; const char *msg; } error_table[] = {
+      { CL_SUCCESS, "success" },
+      { CL_DEVICE_NOT_FOUND, "device not found", },
+      { CL_DEVICE_NOT_AVAILABLE, "device not available", },
+      { CL_COMPILER_NOT_AVAILABLE, "compiler not available", },
+      { CL_MEM_OBJECT_ALLOCATION_FAILURE, "mem object allocation failure", },
+      { CL_OUT_OF_RESOURCES, "out of resources", },
+      { CL_OUT_OF_HOST_MEMORY, "out of host memory", },
+      { CL_PROFILING_INFO_NOT_AVAILABLE, "profiling not available", },
+      { CL_MEM_COPY_OVERLAP, "memcopy overlaps", },
+      { CL_IMAGE_FORMAT_MISMATCH, "image format mismatch", },
+      { CL_IMAGE_FORMAT_NOT_SUPPORTED, "image format not supported", },
+      { CL_BUILD_PROGRAM_FAILURE, "build program failed", },
+      { CL_MAP_FAILURE, "map failed", },
+      { CL_INVALID_VALUE, "invalid value", },
+      { CL_INVALID_DEVICE_TYPE, "invalid device type", },
+      { CL_INVALID_PLATFORM, "invlaid platform",},
+      { CL_INVALID_DEVICE, "invalid device",},
+      { CL_INVALID_CONTEXT, "invalid context",},
+      { CL_INVALID_QUEUE_PROPERTIES, "invalid queue properties",},
+      { CL_INVALID_COMMAND_QUEUE, "invalid command queue",},
+      { CL_INVALID_HOST_PTR, "invalid host ptr",},
+      { CL_INVALID_MEM_OBJECT, "invalid mem object",},
+      { CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, "invalid image format descriptor ",},
+      { CL_INVALID_IMAGE_SIZE, "invalid image size",},
+      { CL_INVALID_SAMPLER, "invalid sampler",},
+      { CL_INVALID_BINARY, "invalid binary",},
+      { CL_INVALID_BUILD_OPTIONS, "invalid build options",},
+      { CL_INVALID_PROGRAM, "invalid program ",},
+      { CL_INVALID_PROGRAM_EXECUTABLE, "invalid program executable",},
+      { CL_INVALID_KERNEL_NAME, "invalid kernel name",},
+      { CL_INVALID_KERNEL_DEFINITION, "invalid definition",},
+      { CL_INVALID_KERNEL, "invalid kernel",},
+      { CL_INVALID_ARG_INDEX, "invalid arg index",},
+      { CL_INVALID_ARG_VALUE, "invalid arg value",},
+      { CL_INVALID_ARG_SIZE, "invalid arg size",},
+      { CL_INVALID_KERNEL_ARGS, "invalid kernel args",},
+      { CL_INVALID_WORK_DIMENSION , "invalid work dimension",},
+      { CL_INVALID_WORK_GROUP_SIZE, "invalid work group size",},
+      { CL_INVALID_WORK_ITEM_SIZE, "invalid work item size",},
+      { CL_INVALID_GLOBAL_OFFSET, "invalid global offset",},
+      { CL_INVALID_EVENT_WAIT_LIST, "invalid event wait list",},
+      { CL_INVALID_EVENT, "invalid event",},
+      { CL_INVALID_OPERATION, "invalid operation",},
+      { CL_INVALID_GL_OBJECT, "invalid gl object",},
+      { CL_INVALID_BUFFER_SIZE, "invalid buffer size",},
+      { CL_INVALID_MIP_LEVEL, "invalid mip level",},
+      { CL_INVALID_GLOBAL_WORK_SIZE, "invalid global work size",},
+      { 0, NULL },
+   };
+   static char unknown[25];
+   int ii;
+
+   for (ii = 0; error_table[ii].msg != NULL; ii++) {
+      if (error_table[ii].code == status) {
+         return error_table[ii].msg;
+      }
+   }
+#ifdef _WIN32
+   _snprintf(unknown, sizeof unknown, "unknown error %d", status);
+#else
+   snprintf(unknown, sizeof(unknown), "unknown error %d", status);
+#endif
+   return unknown;
+}
+
+
+class ProfileInfo{
+   public:
+      char label[128]; 
+      cl_ulong queued;
+      cl_ulong submit;
+      cl_ulong start;
+      cl_ulong end;
+};
+
+
+class KernelArgRef{
+   public:
+      jobject javaArray;        // The java array or direct buffer that this arg is mapped to 
+      bool  isArray;            // true if above is an array
+      cl_uint javaArrayLength;  // the number of elements for arrays (used only when ARRAYLENGTH bit is set for this arg)
+      cl_mem mem;               // the opencl buffer 
+      void *addr;               // we use this temporarily whilst we pin the primitive array
+      cl_uint memMask;          // the mask we used for createBuffer
+      jboolean isCopy;
+      jboolean isPinned;
+      char memSpec[128];       // The string form of the mask we used for create buffer. for debugging
+      ProfileInfo read;
+      ProfileInfo write;
+};
+class JNIContext ; // forward reference
+
+class KernelArg{
+   public:
+      char *name;        // used for debugging printfs
+      jfieldID fieldID;  // The field that this arg represents in the kernel (java), used only for primitive updates
+      jint type;         // a bit mask determining the type of this arg
+      jint sizeInBytes;  // bytes in the array or directBuf
+      jobject javaArg;   // global reference to the corresponding java KernelArg 
+      union{
+         cl_char c;
+         cl_double d;
+         cl_float f;
+         cl_int i;
+         cl_long j;
+         KernelArgRef ref;
+      } value;
+
+      void unpinAbort(JNIEnv *jenv){
+         jenv->ReleasePrimitiveArrayCritical((jarray)value.ref.javaArray, value.ref.addr,JNI_ABORT);
+      }
+      void unpinCommit(JNIEnv *jenv){
+         jenv->ReleasePrimitiveArrayCritical((jarray)value.ref.javaArray, value.ref.addr, 0);
+      }
+      void unpin(JNIEnv *jenv){
+         if (isWrite()){
+            // we only need to commit if the buffer has been written to
+            // we use mode=0 in that case (rather than JNI_COMMIT) because that frees any copy buffer if it exists
+            // in most cases this array will have been pinned so this will not be an issue
+            unpinCommit(jenv);
+         }else {
+            // fast path for a read_only buffer
+            unpinAbort(jenv);
+         }
+         value.ref.isPinned = JNI_FALSE;
+      }
+      void pin(JNIEnv *jenv){
+         value.ref.addr = jenv->GetPrimitiveArrayCritical((jarray)value.ref.javaArray,&value.ref.isCopy);
+         value.ref.isPinned = JNI_TRUE;
+      }
+
+      int isArray(){
+         return(type&com_amd_aparapi_KernelRunner_ARG_ARRAY);
+      }
+      int isRead(){
+         return(type&com_amd_aparapi_KernelRunner_ARG_READ);
+      }
+      int isWrite(){
+         return(type&com_amd_aparapi_KernelRunner_ARG_WRITE);
+      }
+      int isExplicit(){
+         return(type&com_amd_aparapi_KernelRunner_ARG_EXPLICIT);
+      }
+      int usesArrayLength(){
+         return(type&com_amd_aparapi_KernelRunner_ARG_ARRAYLENGTH);
+      }
+      int isExplicitWrite(){
+         return(type&com_amd_aparapi_KernelRunner_ARG_EXPLICIT_WRITE);
+      }
+      int isImplicit(){
+         return(!isExplicit());
+      }
+      int isPrimitive(){
+         return(type&com_amd_aparapi_KernelRunner_ARG_PRIMITIVE);
+      }
+      int isGlobal(){
+         return(type&com_amd_aparapi_KernelRunner_ARG_GLOBAL);
+      }
+      int isFloat(){
+         return(type&com_amd_aparapi_KernelRunner_ARG_FLOAT);
+      }
+      int isLong(){
+         return (type&com_amd_aparapi_KernelRunner_ARG_LONG);
+      }
+      int isInt(){
+         return (type&com_amd_aparapi_KernelRunner_ARG_INT);
+      }
+      int isDouble(){
+         return (type&com_amd_aparapi_KernelRunner_ARG_DOUBLE);
+      }
+      int isBoolean(){
+         return (type&com_amd_aparapi_KernelRunner_ARG_BOOLEAN);
+      }
+      int isByte(){
+         return (type&com_amd_aparapi_KernelRunner_ARG_BYTE);
+      }
+      int isShort(){
+         return (type&com_amd_aparapi_KernelRunner_ARG_SHORT);
+      }
+      int isLocal(){
+         return (type&com_amd_aparapi_KernelRunner_ARG_LOCAL);
+      }
+      int isConstant(){
+         return (type&com_amd_aparapi_KernelRunner_ARG_CONSTANT);
+      }
+      int isAparapiBuf(){
+         return (type&com_amd_aparapi_KernelRunner_ARG_APARAPI_BUF);
+      }
+      int isAparapiBufHasArray(){
+         return (type&com_amd_aparapi_KernelRunner_ARG_APARAPI_BUF_HAS_ARRAY);
+      }
+      int isAparapiBufIsDirect(){
+         return (type&com_amd_aparapi_KernelRunner_ARG_APARAPI_BUF_IS_DIRECT);
+      }
+      int isBackedByArray(){
+         return ( (isArray() && isGlobal()) || ((isGlobal() || isConstant()) && isAparapiBufHasArray()));
+      }
+      int mustReadBuffer(){
+         return(((isArray() && isGlobal())||((isAparapiBuf()&&isGlobal())))&&(isImplicit()&&isWrite()));
+      }
+      int mustWriteBuffer(){
+         return ((isImplicit()&&isRead()&&!isConstant())||(isExplicit()&&isExplicitWrite()));
+      }
+
+};
+
+class JNIContext{
+   private: 
+      jint flags;
+      jboolean valid;
+      cl_platform_id platform;
+      cl_platform_id* platforms;
+      cl_uint platformc;
+   public:
+      JNIEnv *jenv;
+      jobject kernelObject;
+      jint numProcessors;
+      jint maxJTPLocalSize;
+      jclass kernelClass;
+      cl_uint deviceIdc;
+      cl_device_id* deviceIds;
+      cl_int deviceType;
+      cl_context context;
+      cl_command_queue* commandQueues;
+      cl_program program;
+      cl_kernel kernel;
+      jint argc;
+      KernelArg** args;
+      cl_event* executeEvents;
+      cl_event* readEvents;
+      cl_ulong profileBaseTime;
+      jint* readEventArgs;
+      cl_event* writeEvents;
+      jint* writeEventArgs;
+      jboolean firstRun;
+      ProfileInfo exec;
+      FILE* profileFile;
+      // these map to camelCase form of CL_DEVICE_XXX_XXX  For example CL_DEVICE_MAX_COMPUTE_UNITS == maxComputeUnits
+      cl_uint maxComputeUnits;
+      cl_uint maxWorkItemDimensions;
+      size_t maxWorkGroupSize;
+      cl_ulong globalMemSize;
+      cl_ulong localMemSize;
+
+      static JNIContext* getJNIContext(jlong jniContextHandle){
+         return((JNIContext*)jniContextHandle);
+      }
+
+      JNIContext(JNIEnv *_jenv, jobject _kernelObject, jint _flags, jint _numProcessors, jint _maxJTPLocalSize): 
+         jenv(_jenv),
+         kernelObject(jenv->NewGlobalRef(_kernelObject)),
+         kernelClass((jclass)jenv->NewGlobalRef(jenv->GetObjectClass(_kernelObject))), 
+         flags(_flags),
+         numProcessors(_numProcessors),
+         maxJTPLocalSize(_maxJTPLocalSize),
+         platform(NULL),
+         profileBaseTime(0),
+         deviceType(((flags&com_amd_aparapi_KernelRunner_JNI_FLAG_USE_GPU)==com_amd_aparapi_KernelRunner_JNI_FLAG_USE_GPU)?CL_DEVICE_TYPE_GPU:CL_DEVICE_TYPE_CPU),
+         profileFile(NULL), 
+         valid(JNI_FALSE){
+            cl_int status = CL_SUCCESS;
+
+            // create the context using the mechanism described here
+            // http://developer.amd.com/support/KnowledgeBase/Lists/KnowledgeBase/DispForm.aspx?ID=71
+            status = clGetPlatformIDs(0, NULL, &platformc);
+            if (status == CL_SUCCESS && platformc >0) {
+               platforms = new cl_platform_id[platformc];
+               status = clGetPlatformIDs(platformc, platforms, NULL);
+               if (status == CL_SUCCESS){
+                  for (unsigned i = 0; i < platformc; ++i) {
+                     char pbuf[512];
+                     status = clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR, sizeof(pbuf), pbuf, NULL);
+                     if (isVerbose()){
+                        fprintf(stderr, "platform %d %s\n", i, pbuf); 
+                     }
+                     if (!strcmp(pbuf, "Advanced Micro Devices, Inc.")) {
+                        platform = platforms[i];
+                     }
+                  }
+
+                  // Get the # of devices
+                  status = clGetDeviceIDs(platform, deviceType, 0, NULL, &deviceIdc);
+                  if (status == CL_SUCCESS){
+                    
+                     deviceIds = new cl_device_id[deviceIdc];
+                     status = clGetDeviceIDs(platform, deviceType, deviceIdc, deviceIds, NULL);
+                     if (status == CL_SUCCESS){
+                        ASSERT_CL_NO_RETURN("clGetDeviceIDs()"); 
+
+                        GET_DEV_INFO(deviceIds[0], CL_DEVICE_MAX_COMPUTE_UNITS, maxComputeUnits, "%d");
+                        GET_DEV_INFO(deviceIds[0], CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, maxWorkItemDimensions, "%d");
+                        GET_DEV_INFO(deviceIds[0], CL_DEVICE_MAX_WORK_GROUP_SIZE, maxWorkGroupSize, "%d");
+                        GET_DEV_INFO(deviceIds[0], CL_DEVICE_GLOBAL_MEM_SIZE, globalMemSize, "%d");
+                        GET_DEV_INFO(deviceIds[0], CL_DEVICE_LOCAL_MEM_SIZE, localMemSize, "%d");
+                        if (isVerbose()){
+
+                           fprintf(stderr, "device[%p]: Type: ", deviceIds[0]);
+                           if (deviceType & CL_DEVICE_TYPE_DEFAULT) {
+                              //  deviceType &= ~CL_DEVICE_TYPE_DEFAULT;
+                              fprintf(stderr, "Default ");
+                           }else if (deviceType & CL_DEVICE_TYPE_CPU) {
+                              // deviceType &= ~CL_DEVICE_TYPE_CPU;
+                              fprintf(stderr, "CPU ");
+                           }else if (deviceType & CL_DEVICE_TYPE_GPU) {
+                              // deviceType &= ~CL_DEVICE_TYPE_GPU;
+                              fprintf(stderr, "GPU ");
+                           }else if (deviceType & CL_DEVICE_TYPE_ACCELERATOR) {
+                              // deviceType &= ~CL_DEVICE_TYPE_ACCELERATOR;
+                              fprintf(stderr, "Accelerator ");
+                           }else{
+                              fprintf(stderr, "Unknown (0x%llx) ", deviceType);
+                           }
+                           fprintf(stderr, "\n");
+                        }
+                        cl_context_properties cps[3] = { CL_CONTEXT_PLATFORM, (cl_context_properties)platform, 0 };
+                        cl_context_properties* cprops = (NULL == platform) ? NULL : cps;
+                        context = clCreateContextFromType( cprops, deviceType, NULL, NULL, &status);
+                        ASSERT_CL_NO_RETURN("clCreateContextFromType()");
+                        if (status == CL_SUCCESS){
+
+                           valid = JNI_TRUE;
+                        }
+                     }
+                  }
+               }
+            }
+
+         }
+
+      jboolean isValid(){
+         return(valid);
+      }
+      jboolean isProfilingEnabled(){
+         return((flags&com_amd_aparapi_KernelRunner_JNI_FLAG_ENABLE_PROFILING)==com_amd_aparapi_KernelRunner_JNI_FLAG_ENABLE_PROFILING?JNI_TRUE:JNI_FALSE);
+      }
+      jboolean isUsingGPU(){
+         return((flags&com_amd_aparapi_KernelRunner_JNI_FLAG_USE_GPU)==com_amd_aparapi_KernelRunner_JNI_FLAG_USE_GPU?JNI_TRUE:JNI_FALSE);
+      }
+      jboolean isVerbose(){
+         return((flags&com_amd_aparapi_KernelRunner_JNI_FLAG_ENABLE_VERBOSE_JNI)==com_amd_aparapi_KernelRunner_JNI_FLAG_ENABLE_VERBOSE_JNI?JNI_TRUE:JNI_FALSE);
+      }
+
+      ~JNIContext(){
+         cl_int status = CL_SUCCESS;
+         jenv->DeleteGlobalRef(kernelObject);
+         jenv->DeleteGlobalRef(kernelClass);
+         if (context != 0){
+            status = clReleaseContext(context);
+            ASSERT_CL_NO_RETURN("clReleaseContext()");
+            context = (cl_context)0;
+         }
+         if (commandQueues){
+            for (int dev=0; dev<deviceIdc; dev++){
+               status = clReleaseCommandQueue((cl_command_queue)commandQueues[dev]);
+               ASSERT_CL_NO_RETURN("clReleaseCommandQueue()");
+               commandQueues[dev] = (cl_command_queue)0;
+            }
+            delete[] commandQueues; commandQueues = NULL;
+         }
+         if (program != 0){
+            status = clReleaseProgram((cl_program)program);
+            ASSERT_CL_NO_RETURN("clReleaseProgram()");
+            program = (cl_program)0;
+         }
+         if (kernel != 0){
+            status = clReleaseKernel((cl_kernel)kernel);
+            ASSERT_CL_NO_RETURN("clReleaseKernel()");
+            kernel = (cl_kernel)0;
+         }
+         if (platforms){
+            delete []platforms; platforms=NULL;
+         }
+         if (deviceIds){
+            delete [] deviceIds; deviceIds=NULL;
+         }
+         if (argc> 0){
+            for (int i=0; i< argc; i++){
+               KernelArg *arg = args[i];
+               if (!arg->isPrimitive()){
+                  if (arg->value.ref.mem != 0){
+                     status = clReleaseMemObject((cl_mem)arg->value.ref.mem);
+                     ASSERT_CL_NO_RETURN("clReleaseMemObject()");
+                     arg->value.ref.mem = (cl_mem)0;
+                  }
+                  if (arg->value.ref.javaArray != NULL)  {
+                     jenv->DeleteWeakGlobalRef((jweak) arg->value.ref.javaArray);
+                  }
+               }
+               if (arg->name != NULL){
+                  free(arg->name); arg->name = NULL;
+               }
+               if (arg->javaArg != NULL ) {
+                  jenv->DeleteGlobalRef((jobject) arg->javaArg);
+               }
+               delete arg; arg=args[i]=NULL;
+            }
+            delete[] args; args=NULL;
+
+            delete []readEvents; readEvents =NULL;
+            delete []writeEvents; writeEvents = NULL;
+            delete []executeEvents; executeEvents = NULL;
+
+            if (isProfilingEnabled()) {
+               if (profileFile != NULL && profileFile != stderr) {
+                  fclose(profileFile);
+               }
+               delete[] readEventArgs; readEventArgs=0;
+               delete[] writeEventArgs; writeEventArgs=0;
+            } 
+         }
+      }
+
+      /*
+         Release JNI critical pinned arrays before returning to java code
+         */
+      void unpinAll() {
+         for (int i=0; i< argc; i++){
+            KernelArg *arg = args[i];
+            if (arg->isBackedByArray()) {
+               arg->unpin(jenv);
+            }
+         }
+      }
+
+
+};
+
+jclass cacheKernelArgFields(JNIEnv *jenv, jobject jobj){
+   jclass c = jenv->GetObjectClass(jobj); 
+   nameFieldID = jenv->GetFieldID(c, "name", "Ljava/lang/String;"); ASSERT_FIELD(name);
+   typeFieldID = jenv->GetFieldID(c, "type", "I"); ASSERT_FIELD(type);
+   javaArrayFieldID = jenv->GetFieldID(c, "javaArray", "Ljava/lang/Object;"); ASSERT_FIELD(javaArray);
+   bytesPerLocalSizeFieldID = jenv->GetFieldID(c, "bytesPerLocalSize", "I"); ASSERT_FIELD(bytesPerLocalSize);
+   sizeInBytesFieldID = jenv->GetFieldID(c, "sizeInBytes", "I"); ASSERT_FIELD(sizeInBytes);
+   numElementsFieldID = jenv->GetFieldID(c, "numElements", "I"); ASSERT_FIELD(numElements);
+   return(c);
+}
+
+JNIEXPORT jint JNICALL Java_com_amd_aparapi_KernelRunner_disposeJNI(JNIEnv *jenv, jobject jobj, jlong jniContextHandle) {
+   cl_int status = CL_SUCCESS;
+   JNIContext* jniContext = JNIContext::getJNIContext(jniContextHandle);
+   if (jniContext != NULL){
+      delete jniContext;//free(jniContext);
+      jniContext = NULL;
+   }
+   return(status);
+}
+
+void idump(char *str, void *ptr, int size){
+   int * iptr = (int *)ptr;
+   for (int i=0; i<size/sizeof(int); i++){
+      fprintf(stderr, "%s%4d %d\n", str, i, iptr[i]);
+   }
+}
+
+void fdump(char *str, void *ptr, int size){
+   float * fptr = (float *)ptr;
+   for (int i=0; i<size/sizeof(float); i++){
+      fprintf(stderr, "%s%4d %6.2f\n", str, i, fptr[i]);
+   }
+}
+
+
+jint writeProfileInfo(JNIContext* jniContext){
+   cl_ulong currSampleBaseTime = -1;
+   int pos = 1;
+
+   if (jniContext->firstRun) {
+      fprintf(jniContext->profileFile, "# PROFILE Name, queued, submit, start, end (microseconds)\n");
+   }       
+
+   // A read by a user kernel means the OpenCL layer wrote to the kernel and vice versa
+   for (int i=0; i< jniContext->argc; i++){
+      KernelArg *arg=jniContext->args[i];
+      if (arg->isBackedByArray() && arg->isRead()){
+
+         // Initialize the base time for this sample
+         if (currSampleBaseTime == -1) {
+            currSampleBaseTime = arg->value.ref.write.queued;
+         } 
+
+         if (jniContext->profileBaseTime == 0){
+            jniContext->profileBaseTime = arg->value.ref.write.queued;
+
+            // Write the base time as the first item in the csv
+            //fprintf(jniContext->profileFile, "%llu,", jniContext->profileBaseTime);
+         }
+
+         fprintf(jniContext->profileFile, "%d write %s,", pos++, arg->name);
+
+         fprintf(jniContext->profileFile, "%lu,%lu,%lu,%lu,",  
+               (arg->value.ref.write.queued - currSampleBaseTime)/1000, 
+               (arg->value.ref.write.submit - currSampleBaseTime)/1000, 
+               (arg->value.ref.write.start - currSampleBaseTime)/1000, 
+               (arg->value.ref.write.end - currSampleBaseTime)/1000);
+      }
+   }
+
+   if (jniContext->profileBaseTime == 0){
+      jniContext->profileBaseTime = jniContext->exec.queued;
+
+      // Write the base time as the first item in the csv
+      //fprintf(jniContext->profileFile, "%llu,", jniContext->profileBaseTime);
+   }
+
+   // Initialize the base time for this sample if necessary
+   if (currSampleBaseTime == -1) {
+      currSampleBaseTime = jniContext->exec.queued;
+   } 
+
+   // exec 
+   fprintf(jniContext->profileFile, "%d exec,", pos++);
+
+   fprintf(jniContext->profileFile, "%lu,%lu,%lu,%lu,",  
+         (jniContext->exec.queued - currSampleBaseTime)/1000, 
+         (jniContext->exec.submit - currSampleBaseTime)/1000, 
+         (jniContext->exec.start - currSampleBaseTime)/1000, 
+         (jniContext->exec.end - currSampleBaseTime)/1000);
+
+   // 
+   if ( jniContext->argc == 0 ) {
+      fprintf(jniContext->profileFile, "\n");
+   } else { 
+      for (int i=0; i< jniContext->argc; i++){
+         KernelArg *arg=jniContext->args[i];
+         if (arg->isBackedByArray() && arg->isWrite()){
+            if (jniContext->profileBaseTime == 0){
+               jniContext->profileBaseTime = arg->value.ref.read.queued;
+
+               // Write the base time as the first item in the csv
+               //fprintf(jniContext->profileFile, "%llu,", jniContext->profileBaseTime);               
+            }
+
+            // Initialize the base time for this sample
+            if (currSampleBaseTime == -1) {
+               currSampleBaseTime = arg->value.ref.read.queued;
+            }
+
+            fprintf(jniContext->profileFile, "%d read %s,", pos++, arg->name);
+
+            fprintf(jniContext->profileFile, "%lu,%lu,%lu,%lu,",  
+                  (arg->value.ref.read.queued - currSampleBaseTime)/1000, 
+                  (arg->value.ref.read.submit - currSampleBaseTime)/1000, 
+                  (arg->value.ref.read.start - currSampleBaseTime)/1000, 
+                  (arg->value.ref.read.end - currSampleBaseTime)/1000);
+         }
+      }
+   }
+   fprintf(jniContext->profileFile, "\n");
+   return(0);
+}
+
+// Should failed profiling abort the run and return early?
+cl_int profile(ProfileInfo *profileInfo, cl_event *event){
+   cl_int status = CL_SUCCESS;
+   status = clGetEventProfilingInfo(*event, CL_PROFILING_COMMAND_QUEUED, sizeof(profileInfo->queued), &(profileInfo->queued), NULL);
+   ASSERT_CL( "clGetEventProfiliningInfo() QUEUED");
+   status = clGetEventProfilingInfo(*event, CL_PROFILING_COMMAND_SUBMIT, sizeof(profileInfo->submit), &(profileInfo->submit), NULL);
+   ASSERT_CL( "clGetEventProfiliningInfo() SUBMIT");
+   status = clGetEventProfilingInfo(*event, CL_PROFILING_COMMAND_START, sizeof(profileInfo->start), &(profileInfo->start), NULL);
+   ASSERT_CL( "clGetEventProfiliningInfo() START");
+   status = clGetEventProfilingInfo(*event, CL_PROFILING_COMMAND_END, sizeof(profileInfo->end), &(profileInfo->end), NULL);
+   ASSERT_CL( "clGetEventProfiliningInfo() END");
+   return status;
+}
+
+
+
+
+jint updateKernel(JNIEnv *jenv, jobject jobj, JNIContext* jniContext) {
+   cl_int status = CL_SUCCESS;
+   if (jniContext != NULL){
+      // we need to step through the array of KernelArg's to create the info required to create the cl_mem buffers.
+      for (jint i=0; i<jniContext->argc; i++){ 
+         KernelArg *arg=jniContext->args[i];
+
+         arg->type = jenv->GetIntField(arg->javaArg, typeFieldID);
+         if (jniContext->isVerbose()){
+            fprintf(stderr, "got type for %s: %08x\n", arg->name, arg->type);
+         }
+         if (!arg->isPrimitive()) {
+            // Following used for all primitive arrays, object arrays  and nio Buffers
+            jarray newRef = (jarray)jenv->GetObjectField(arg->javaArg, javaArrayFieldID);
+            if (jniContext->isVerbose()){
+
+               fprintf(stderr, "testing for Resync javaArray %s: old=%p, new=%p\n", arg->name, arg->value.ref.javaArray, newRef);         
+            }
+
+            jboolean isSame = jenv->IsSameObject( newRef, arg->value.ref.javaArray);
+            if (isSame == JNI_FALSE) {
+               if (jniContext->isVerbose()){
+                  fprintf(stderr, "Resync javaArray for %s: %p  %p\n", arg->name, newRef, arg->value.ref.javaArray);         
+               }
+               // Free previous ref if any
+               if (arg->value.ref.javaArray != NULL) {
+                  jenv->DeleteWeakGlobalRef((jweak) arg->value.ref.javaArray);
+                  if (jniContext->isVerbose()){
+                     fprintf(stderr, "DeleteWeakGlobalRef for %s: %p\n", arg->name, arg->value.ref.javaArray);         
+                  }
+               }
+
+               // need to free opencl buffers, run will reallocate later
+               if (arg->value.ref.mem != 0) {
+                  //fprintf(stderr, "-->releaseMemObject[%d]\n", i);
+                  status = clReleaseMemObject((cl_mem)arg->value.ref.mem);
+                  //fprintf(stderr, "<--releaseMemObject[%d]\n", i);
+                  ASSERT_CL("clReleaseMemObject()");
+                  arg->value.ref.mem = (cl_mem)0;
+               }
+
+               arg->value.ref.mem = (cl_mem) 0;
+               arg->value.ref.addr = NULL;
+
+               // Capture new array ref from the kernel arg object
+
+               if (newRef != NULL) {
+                  arg->value.ref.javaArray = (jarray)jenv->NewWeakGlobalRef((jarray)newRef);
+                  if (jniContext->isVerbose()){
+                     fprintf(stderr, "NewWeakGlobalRef for %s, set to %p\n", arg->name,
+                           arg->value.ref.javaArray);         
+                  }
+               } else {
+                  arg->value.ref.javaArray = NULL;
+               }
+               arg->value.ref.isArray = !arg->isAparapiBufIsDirect();
+
+               // Save the sizeInBytes which was set on the java side
+               arg->sizeInBytes = jenv->GetIntField(arg->javaArg, sizeInBytesFieldID);
+
+               if (jniContext->isVerbose()){
+                  fprintf(stderr, "updateKernel, args[%d].sizeInBytes=%d\n", i, arg->sizeInBytes);
+               }
+            } // !is_same
+         }
+      } // for each arg
+   } // if jniContext != NULL
+
+   return(status);
+}
+
+
+
+JNIEXPORT jint JNICALL Java_com_amd_aparapi_KernelRunner_runKernelJNI(JNIEnv *jenv,
+      jobject jobj, jlong jniContextHandle, jint globalSize, jint localSize, jboolean needSync,
+      jboolean useNullForLocalSize, jint passes) {
+
+   cl_int status = CL_SUCCESS;
+   JNIContext* jniContext = JNIContext::getJNIContext(jniContextHandle);
+   if (jniContext->isVerbose()){
+      timer.start();
+   }
+
+   // Need to capture array refs
+   if (jniContext->firstRun || needSync) {
+      updateKernel(jenv, jobj, jniContext );
+      if (jniContext->isVerbose()){
+         fprintf(stderr, "back from updateKernel\n");
+      }
+   }
+
+   int writeEventCount = 0;
+
+   // kernelArgPos is used to keep track of the kernel arg position, it can 
+   // differ from "i" due to insertion of javaArrayLength args which are not
+   // fields read from the kernel object.
+   int kernelArgPos = 0;
+
+   for (int i=0; i< jniContext->argc; i++){
+      KernelArg *arg = jniContext->args[i];
+      // TODO: see if we can get rid of this read
+      arg->type = jenv->GetIntField(arg->javaArg, typeFieldID);
+      if (jniContext->isVerbose()){
+         fprintf(stderr, "got type for arg %d, %s, type=%08x\n", i, arg->name, arg->type);
+      }
+      if (!arg->isPrimitive() && !arg->isLocal()) {
+         // pin the arrays so that GC does not move them during the call
+
+         // get the C memory address for the region being transferred
+         // this uses different JNI calls for arrays vs. directBufs
+         void * prevAddr =  arg->value.ref.addr;
+         if (arg->value.ref.isArray) {
+            arg->pin(jenv);
+         } else if (arg->isAparapiBufIsDirect()) {
+            // different call used for directbuffers
+            arg->value.ref.addr = jenv->GetDirectBufferAddress(arg->value.ref.javaArray);
+         }
+
+         if (jniContext->isVerbose()){
+            fprintf(stderr, "runKernel: arrayOrBuf ref %p, oldAddr=%p, newAddr=%p, ref.mem=%p, isArray=%d\n",
+                  arg->value.ref.javaArray, 
+                  prevAddr,
+                  arg->value.ref.addr,
+                  arg->value.ref.mem,
+                  arg->value.ref.isArray );
+            fprintf(stderr, "at memory addr %p, contents: ", arg->value.ref.addr);
+            unsigned char *pb = (unsigned char *) arg->value.ref.addr;
+            for (int k=0; k<8; k++) {
+               fprintf(stderr, "%02x ", pb[k]);
+            }
+            fprintf(stderr, "\n" );
+         }
+         // record whether object moved 
+         // if we see that isCopy was returned by getPrimitiveArrayCritical, treat that as a move
+         bool objectMoved = (arg->value.ref.addr != prevAddr) || arg->value.ref.isCopy;
+
+#ifdef VERBOSE_EXPLICIT
+         if (arg->isExplicit() && arg->isExplicitWrite()){
+            fprintf(stderr, "explicit write of %s\n",  arg->name);
+         }
+#endif
+
+         if (jniContext->firstRun || (arg->value.ref.mem == 0) || objectMoved ){
+            // if either this is the first run or user changed input array
+            // or gc moved something, then we create buffers/args
+            cl_uint mask = CL_MEM_USE_HOST_PTR;
+            if (arg->isRead() && arg->isWrite()) mask |= CL_MEM_READ_WRITE;
+            else if (arg->isRead() && !arg->isWrite()) mask |= CL_MEM_READ_ONLY;
+            else if (arg->isWrite()) mask |= CL_MEM_WRITE_ONLY;
+            arg->value.ref.memMask = mask;
+            if (jniContext->isVerbose()){
+               strcpy(arg->value.ref.memSpec,"CL_MEM_USE_HOST_PTR");
+               if (mask & CL_MEM_READ_WRITE) strcat(arg->value.ref.memSpec,"|CL_MEM_READ_WRITE");
+               if (mask & CL_MEM_READ_ONLY) strcat(arg->value.ref.memSpec,"|CL_MEM_READ_ONLY");
+               if (mask & CL_MEM_WRITE_ONLY) strcat(arg->value.ref.memSpec,"|CL_MEM_WRITE_ONLY");
+
+               fprintf(stderr, "%s %d clCreateBuffer(context, %s, size=%08x bytes, address=%08x, &status)\n", arg->name, 
+                     i, arg->value.ref.memSpec, arg->sizeInBytes, arg->value.ref.addr);
+            }
+            arg->value.ref.mem = clCreateBuffer(jniContext->context, arg->value.ref.memMask, 
+                  arg->sizeInBytes, arg->value.ref.addr, &status);
+
+            if (status != CL_SUCCESS) {
+               PRINT_CL_ERR(status, "clCreateBuffer");
+               jniContext->unpinAll();
+               return status;
+            }
+
+            status = clSetKernelArg(jniContext->kernel, kernelArgPos++, sizeof(cl_mem), (void *)&(arg->value.ref.mem));                  
+            if (status != CL_SUCCESS) {
+               PRINT_CL_ERR(status, "clSetKernelArg (array)");
+               jniContext->unpinAll();
+               return status;
+            }
+
+            // Add the array length if needed
+            if (arg->usesArrayLength()){
+               arg->value.ref.javaArrayLength = jenv->GetIntField(arg->javaArg, numElementsFieldID);
+               status = clSetKernelArg(jniContext->kernel, kernelArgPos++, sizeof(jint), &(arg->value.ref.javaArrayLength));
+
+               if (jniContext->isVerbose()){
+                  fprintf(stderr, "runKernel arg %d %s, javaArrayLength = %d\n", i, arg->name, arg->value.ref.javaArrayLength);
+               }
+               if (status != CL_SUCCESS) {
+                  PRINT_CL_ERR(status, "clSetKernelArg (array length)");
+                  jniContext->unpinAll();
+                  return status;
+               }
+            }
+         } else {
+            // Keep the arg position in sync if no updates were required
+            kernelArgPos++;
+            if (arg->usesArrayLength()){
+               kernelArgPos++;
+            }
+         }
+
+         // we only enqueue a write if we know the kernel actually reads the buffer or if there is an explicit write pending
+         // the default behavior for Constant buffers is also that there is no write enqueued unless explicit
+
+         if (arg->mustWriteBuffer()){
+#ifdef VERBOSE_EXPLICIT
+            if (arg->isExplicit() && arg->isExplicitWrite()){
+               fprintf(stderr, "writing explicit buffer %d %s\n", i, arg->name);
+            }
+#endif
+            if (jniContext->isVerbose()){
+               fprintf(stderr, "%s writing buffer %d %s\n",  (arg->isExplicit() ? "explicitly" : ""), 
+                     i, arg->name);
+            }
+            if (jniContext->isProfilingEnabled()) {
+               jniContext->writeEventArgs[writeEventCount]=i;
+            }
+
+            status = clEnqueueWriteBuffer(jniContext->commandQueues[0], arg->value.ref.mem, CL_FALSE, 0, 
+                  arg->sizeInBytes, arg->value.ref.addr, 0, NULL, &(jniContext->writeEvents[writeEventCount++]));
+            if (status != CL_SUCCESS) {
+               PRINT_CL_ERR(status, "clEnqueueWriteBuffer");
+               jniContext->unpinAll();
+               return status;
+            }
+            if (arg->isExplicit() && arg->isExplicitWrite()){
+               arg->type &= ~com_amd_aparapi_KernelRunner_ARG_EXPLICIT_WRITE;
+#ifdef VERBOSE_EXPLICIT
+               fprintf(stderr, "clearing explicit buffer bit %d %s\n", i, arg->name);
+#endif
+               jenv->SetIntField(arg->javaArg, typeFieldID,arg->type );
+            }
+         }
+      } else if (arg->isLocal()){
+         if (jniContext->firstRun){
+            // must multiply perlocalByteSize by localSize to get real opencl buffer size
+            int bytesPerLocalSize = jenv->GetIntField(arg->javaArg, bytesPerLocalSizeFieldID);
+            int adjustedLocalBufSize = bytesPerLocalSize * localSize;
+
+            if (jniContext->isVerbose()){
+               fprintf(stderr, "ISLOCAL, clSetKernelArg(jniContext->kernel, %d, %d, NULL);\n", i, adjustedLocalBufSize);
+            }
+            status = clSetKernelArg(jniContext->kernel, kernelArgPos++, adjustedLocalBufSize, NULL);
+            if (status != CL_SUCCESS) {
+               PRINT_CL_ERR(status, "clSetKernelArg() (local)");
+               jniContext->unpinAll();
+               return status;
+            }
+         } else {
+            // Keep the arg position in sync if no updates were required
+            kernelArgPos++;
+            if (arg->usesArrayLength()){
+               kernelArgPos++;
+            }
+         }
+      }else{  // primitive arguments
+
+         // we need to reflectively sync the value out of the kernel object
+         if (arg->isFloat()){
+            arg->value.f = jenv->GetFloatField(jniContext->kernelObject, arg->fieldID);
+            //fprintf(stderr, "float arg %d\n", arg->value.f); 
+         }else if (arg->isInt()){
+            arg->value.i = jenv->GetIntField(jniContext->kernelObject, arg->fieldID);
+            //fprintf(stderr, "int arg %d\n", arg->value.i); 
+         }else if (arg->isBoolean()){
+            arg->value.c = jenv->GetBooleanField(jniContext->kernelObject, arg->fieldID);
+            //fprintf(stderr, "boolean arg %d\n", arg->value.c); 
+         }else if (arg->isByte()){
+            arg->value.c = jenv->GetByteField(jniContext->kernelObject, arg->fieldID);
+            //fprintf(stderr, "byte arg %d\n", arg->value.c); 
+         }else if (arg->isLong()){
+            arg->value.j = jenv->GetLongField(jniContext->kernelObject, arg->fieldID);
+            //fprintf(stderr, "long arg %d\n", arg->value.c); 
+         }else if (arg->isDouble()){
+            arg->value.d = jenv->GetDoubleField(jniContext->kernelObject, arg->fieldID);
+            //fprintf(stderr, "double arg %d\n", arg->value.c); 
+         }
+
+         if (jniContext->isVerbose()){
+            fprintf(stderr, "clSetKernelArg %s: %d %d %d 0x%08x\n", arg->name, i, kernelArgPos, 
+                  arg->sizeInBytes, arg->value);         
+         }
+         status = clSetKernelArg(jniContext->kernel, kernelArgPos++, arg->sizeInBytes, &(arg->value));
+         if (status != CL_SUCCESS) {
+            PRINT_CL_ERR(status, "clSetKernelArg() (value)");
+            jniContext->unpinAll();
+            return status;
+         }
+      }
+   }  // for each arg
+
+   size_t globalSizeAsSizeT = (globalSize /jniContext->deviceIdc);
+   size_t localSizeAsSizeT = localSize;
+
+   // To support multiple passes we add a 'secret' final arg called 'passid' and just schedule multiple enqueuendrange kernels.  Each of which having a separate value of passid
+
+   for (int passid=0; passid<passes; passid++){
+      for (int dev =0; dev < jniContext->deviceIdc; dev++){
+         size_t offset = (size_t)((globalSize/jniContext->deviceIdc)*dev);
+         status = clSetKernelArg(jniContext->kernel, kernelArgPos, sizeof(passid), &(passid));
+         if (status != CL_SUCCESS) {
+            PRINT_CL_ERR(status, "clSetKernelArg() (passid)");
+            jniContext->unpinAll();
+            return status;
+         }
+
+         // four options here due to passid
+         if (passid == 0 && passes==1){
+            //fprintf(stderr, "setting passid to %d of %d first and last\n", passid, passes);
+            // there is one pass and this is it
+            // enqueue depends on write enqueues 
+            // we don't block but and we populate the executeEvents
+            status = clEnqueueNDRangeKernel(jniContext->commandQueues[dev], jniContext->kernel, 1, &offset, &globalSizeAsSizeT,
+                  useNullForLocalSize ? NULL : &localSizeAsSizeT,
+                  writeEventCount, writeEventCount?jniContext->writeEvents:NULL, &jniContext->executeEvents[dev]);
+         }else if (passid == 0){
+            //fprintf(stderr, "setting passid to %d of %d first not last\n", passid, passes);
+            // this is the first of multiple passes
+            // enqueue depends on write enqueues 
+            // we block but do not populate executeEvents (only the last pass does this)
+            status = clEnqueueNDRangeKernel(jniContext->commandQueues[dev], jniContext->kernel, 1, &offset, &globalSizeAsSizeT,
+                  useNullForLocalSize ? NULL : &localSizeAsSizeT,
+                  writeEventCount, writeEventCount?jniContext->writeEvents:NULL, &jniContext->executeEvents[dev]);
+
+         }else if (passid < passes-1){
+            // we are in some middle pass (neither first or last) 
+            // we don't depend on write enqueues
+            // we block and do not supply executeEvents (only the last pass does this)
+            //fprintf(stderr, "setting passid to %d of %d not first not last\n", passid, passes);
+            status = clEnqueueNDRangeKernel(jniContext->commandQueues[dev], jniContext->kernel, 1, &offset, &globalSizeAsSizeT,
+                  useNullForLocalSize ? NULL : &localSizeAsSizeT, 0, NULL, &jniContext->executeEvents[dev]);
+         }else{
+            // we are the last pass of >1
+            // we don't depend on write enqueues
+            // we block and supply executeEvents
+            //fprintf(stderr, "setting passid to %d of %d  last\n", passid, passes);
+            status = clEnqueueNDRangeKernel(jniContext->commandQueues[dev], jniContext->kernel, 1, &offset, &globalSizeAsSizeT,
+                  useNullForLocalSize ? NULL : &localSizeAsSizeT, 0, NULL, &jniContext->executeEvents[dev]);
+         }
+
+
+         if (status != CL_SUCCESS) {
+            PRINT_CL_ERR(status, "clEnqueueNDRangeKernel()");
+            fprintf(stderr, "after clEnqueueNDRangeKernel, globalSize=%d localSize=%d usingNull=%d\n", (int)globalSizeAsSizeT, (int)localSizeAsSizeT, useNullForLocalSize);
+            jniContext->unpinAll();
+            return status;
+         }
+      }
+      if (passid < passes-1){
+         // we need to wait for the executions to complete...
+         status = clWaitForEvents(jniContext->deviceIdc,  jniContext->executeEvents);
+         if (status != CL_SUCCESS) {
+            PRINT_CL_ERR(status, "clWaitForEvents() execute events mid pass");
+            jniContext->unpinAll();
+            return status;
+         }
+
+         for (int dev = 0; dev < jniContext->deviceIdc; dev++){
+            status = clReleaseEvent(jniContext->executeEvents[dev]);
+            if (status != CL_SUCCESS) {
+               PRINT_CL_ERR(status, "clReleaseEvent() read event");
+               jniContext->unpinAll();
+               return status;
+            }
+         }
+      }
+   }
+
+   int readEventCount = 0;
+
+   for (int i=0; i< jniContext->argc; i++){
+      KernelArg *arg = jniContext->args[i];
+
+      if (arg->mustReadBuffer()){
+         if (jniContext->isProfilingEnabled()) {
+            jniContext->readEventArgs[readEventCount]=i;
+         }
+         if (jniContext->isVerbose()){
+            fprintf(stderr, "reading buffer %d %s\n", i, arg->name);
+         }
+
+         status = clEnqueueReadBuffer(jniContext->commandQueues[0], arg->value.ref.mem, CL_FALSE, 0, 
+               arg->sizeInBytes,arg->value.ref.addr , jniContext->deviceIdc, jniContext->executeEvents, &(jniContext->readEvents[readEventCount++]));
+         if (status != CL_SUCCESS) {
+            PRINT_CL_ERR(status, "clEnqueueReadBuffer()");
+            jniContext->unpinAll();
+            return status;
+         }
+      }
+   }
+
+   // don't change the order here
+   // We wait for the reads which each depend on the execution, which depends on the writes ;)
+   // So after the reads have completed, we can release the execute and writes.
+
+   if (readEventCount >0){
+      status = clWaitForEvents(readEventCount, jniContext->readEvents);
+      if (status != CL_SUCCESS) {
+         PRINT_CL_ERR(status, "clWaitForEvents() read events");
+         jniContext->unpinAll();
+         return status;
+      }
+
+      for (int i=0; i< readEventCount; i++){
+         if (jniContext->isProfilingEnabled()) {
+            status = profile(&jniContext->args[jniContext->readEventArgs[i]]->value.ref.read, &jniContext->readEvents[i]);
+            if (status != CL_SUCCESS) {
+               jniContext->unpinAll();
+               return status;
+            }
+         }
+         status = clReleaseEvent(jniContext->readEvents[i]);
+         if (status != CL_SUCCESS) {
+            PRINT_CL_ERR(status, "clReleaseEvent() read event");
+            jniContext->unpinAll();
+            return status;
+         }
+      }
+   } else {
+      // if readEventCount == 0 then we don't need any reads so we just wait for the executions to complete
+      status = clWaitForEvents(jniContext->deviceIdc, jniContext->executeEvents);
+      if (status != CL_SUCCESS) {
+         PRINT_CL_ERR(status, "clWaitForEvents() execute event");
+         jniContext->unpinAll();
+         return status;
+      }
+   }
+
+   if (jniContext->isProfilingEnabled()) {
+      status = profile(&jniContext->exec, &jniContext->executeEvents[0]);
+      if (status != CL_SUCCESS) {
+         jniContext->unpinAll();
+         return status;
+      }
+   }
+
+   // extract the execution status from the executeEvent
+   cl_int executeStatus;
+   status = clGetEventInfo(jniContext->executeEvents[0], CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(cl_int), &executeStatus, NULL);
+   if (status != CL_SUCCESS) {
+      PRINT_CL_ERR(status, "clGetEventInfo() execute event");
+      jniContext->unpinAll();
+      return status;
+   }
+   if (executeStatus != CL_SUCCESS) {
+      // it should definitely not be negative, but since we did a wait above, it had better be CL_COMPLETE==CL_SUCCESS
+      PRINT_CL_ERR(executeStatus, "Execution status of execute event");
+      jniContext->unpinAll();
+      return executeStatus;
+   }
+
+   for (int dev=0; dev<jniContext->deviceIdc; dev++){
+
+      status = clReleaseEvent(jniContext->executeEvents[dev]);
+      if (status != CL_SUCCESS) {
+         PRINT_CL_ERR(status, "clReleaseEvent() execute event");
+         jniContext->unpinAll();
+         return status;
+      }
+   }
+
+   for (int i=0; i< writeEventCount; i++){
+      if (jniContext->isProfilingEnabled()) {
+         profile(&jniContext->args[jniContext->writeEventArgs[i]]->value.ref.write, &jniContext->writeEvents[i]);
+      }
+      status = clReleaseEvent(jniContext->writeEvents[i]);
+      if (status != CL_SUCCESS) {
+         PRINT_CL_ERR(status, "clReleaseEvent() write event");
+         jniContext->unpinAll();
+         return status;
+      }
+   }
+
+   jniContext->unpinAll();
+
+   if (jniContext->isProfilingEnabled()) {
+      writeProfileInfo(jniContext);
+   }
+
+   jniContext->firstRun = false;
+   if (jniContext->isVerbose()){
+      timer.end("elapsed");
+   }
+
+   //fprintf(stderr, "About to return %d from exec\n", status);
+   return(status);
+}
+
+
+// we return the JNIContext from here 
+JNIEXPORT jlong JNICALL Java_com_amd_aparapi_KernelRunner_initJNI(JNIEnv *jenv, jclass clazz, jobject kernelObject, 
+      jint flags, jint numProcessors,
+      jint maxJTPLocalSize) {
+   cl_int status = CL_SUCCESS;
+   JNIContext* jniContext = new JNIContext(jenv, kernelObject, flags, numProcessors, maxJTPLocalSize);
+   if (jniContext->isValid()){
+      return((jlong)jniContext);
+   }else{
+      return(0L);
+   }
+}
+
+
+JNIEXPORT jlong JNICALL Java_com_amd_aparapi_KernelRunner_buildProgramJNI(JNIEnv *jenv, jobject jobj, jlong jniContextHandle, jstring source) {
+   JNIContext* jniContext = JNIContext::getJNIContext(jniContextHandle);
+   if (jniContext == NULL){
+      return 0;
+   }
+
+   cl_int status = CL_SUCCESS;
+   const char *sourceChars = jenv->GetStringUTFChars(source, NULL);
+   CHECK(sourceChars == NULL, "jenv->GetStringUTFChars() returned null" );
+
+   size_t sourceSize[] = { strlen(sourceChars) };
+   jniContext->program = clCreateProgramWithSource( jniContext->context, 1, &sourceChars, sourceSize, &status); 
+   jenv->ReleaseStringUTFChars(source, sourceChars);
+   ASSERT_CL("clCreateProgramWithSource()");
+
+   status = clBuildProgram(jniContext->program, jniContext->deviceIdc, jniContext->deviceIds, NULL, NULL, NULL);
+
+   if(status == CL_BUILD_PROGRAM_FAILURE) {
+      cl_int logStatus;
+      size_t buildLogSize = 0;
+      status = clGetProgramBuildInfo(jniContext->program, jniContext->deviceIds[0], 
+            CL_PROGRAM_BUILD_LOG, buildLogSize, NULL, &buildLogSize);
+      ASSERT_CL("clGetProgramBuildInfo()");
+      char * buildLog = new char[buildLogSize];
+      CHECK(buildLog == NULL, "Failed to allocate host memory. (buildLog)");
+      memset(buildLog, 0, buildLogSize);
+      status = clGetProgramBuildInfo (jniContext->program, jniContext->deviceIds[0], 
+            CL_PROGRAM_BUILD_LOG, buildLogSize, buildLog, NULL);
+      ASSERT_CL("clGetProgramBuildInfo()");
+
+      fprintf(stderr, "clBuildProgram failed");
+      fprintf(stderr, "\n************************************************\n");
+      fprintf(stderr, "%s", buildLog);
+      fprintf(stderr, "\n************************************************\n\n\n");
+      delete []buildLog;
+      return(0);
+   }
+
+   jniContext->kernel = clCreateKernel(jniContext->program, "run", &status);
+   ASSERT_CL("clCreateKernel()");
+
+   cl_command_queue_properties queue_props = 0;
+   if (jniContext->isProfilingEnabled()) {
+      queue_props |= CL_QUEUE_PROFILING_ENABLE;
+   }
+
+   jniContext->commandQueues= new cl_command_queue[jniContext->deviceIdc];
+   for (int dev=0; dev < jniContext->deviceIdc; dev++){
+      jniContext->commandQueues[dev]=clCreateCommandQueue(jniContext->context, (cl_device_id)jniContext->deviceIds[dev],
+            queue_props,
+            &status);
+      ASSERT_CL("clCreateCommandQueue()");
+   }
+
+   if (jniContext->isProfilingEnabled()) {
+      // compute profile filename
+#if defined (_WIN32)
+      jint pid = GetCurrentProcessId();
+#else
+      pid_t pid = getpid();
+#endif
+      // indicate cpu or gpu
+      // timestamp
+      // kernel name
+
+      jclass classMethodAccess = jenv->FindClass("java/lang/Class"); 
+      jmethodID getNameID=jenv->GetMethodID(classMethodAccess,"getName","()Ljava/lang/String;");
+      jstring className = (jstring)jenv->CallObjectMethod(jniContext->kernelClass, getNameID);
+      const char *classNameChars = jenv->GetStringUTFChars(className, NULL);
+
+#define TIME_STR_LEN 200
+
+      char timeStr[TIME_STR_LEN];
+      struct tm *tmp;
+      time_t t = time(NULL);
+      tmp = localtime(&t);
+      if (tmp == NULL) {
+         perror("localtime");
+      }
+      //strftime(timeStr, TIME_STR_LEN, "%F.%H%M%S", tmp);  %F seemed to cause a core dump
+      strftime(timeStr, TIME_STR_LEN, "%H%M%S", tmp);
+
+      char* fnameStr = new char[strlen(classNameChars) + strlen(timeStr) + 128];
+
+      //sprintf(fnameStr, "%s.%s.%d.%llx\n", classNameChars, timeStr, pid, jniContext);
+      sprintf(fnameStr, "aparapiprof.%s.%d.%016lx", timeStr, pid, (unsigned long)jniContext);
+      jenv->ReleaseStringUTFChars(className, classNameChars);
+
+      FILE* profileFile = fopen(fnameStr, "w");
+      if (profileFile != NULL) {
+         jniContext->profileFile = profileFile;
+      } else {
+         jniContext->profileFile = stderr;
+         fprintf(stderr, "Could not open profile data file %s, reverting to stderr\n", fnameStr);
+      }
+      delete []fnameStr;
+   }
+
+   return((jlong)jniContext);
+}
+
+
+// this is called once when the arg list is first determined for this kernel
+JNIEXPORT jint JNICALL Java_com_amd_aparapi_KernelRunner_setArgsJNI(JNIEnv *jenv, jobject jobj, jlong jniContextHandle, jobjectArray argArray, jint argc) {
+   JNIContext* jniContext = JNIContext::getJNIContext(jniContextHandle);
+   cl_int status = CL_SUCCESS;
+   if (jniContext != NULL){      
+      jniContext->argc = argc;
+      jniContext->args = new KernelArg*[jniContext->argc];
+      jniContext->firstRun = true;
+
+      // Step through the array of KernelArg's to capture the type data for the Kernel's data members.
+      for (jint i=0; i<jniContext->argc; i++){ 
+         KernelArg* arg = jniContext->args[i] = new KernelArg;
+
+
+         jobject argObj = jenv->GetObjectArrayElement(argArray, i);
+         if (argClazz == 0){
+            argClazz = cacheKernelArgFields(jenv, argObj);
+         }
+         arg->javaArg = jenv->NewGlobalRef(argObj);   // save a global ref to the java Arg Object
+
+         arg->type = jenv->GetIntField(argObj, typeFieldID);
+         jstring name  = (jstring)jenv->GetObjectField(argObj, nameFieldID);
+         const char *nameChars = jenv->GetStringUTFChars(name, NULL);
+         arg->name=strdup(nameChars);
+         jenv->ReleaseStringUTFChars(name, nameChars);
+#ifdef VERBOSE_EXPLICIT
+         if (arg->isExplicit()){
+            fprintf(stderr, "%s is explicit!\n", arg->name);
+         }
+#endif
+
+         if (arg->isPrimitive()) {
+            // for primitives, we cache the fieldID for that field in the kernel's arg object
+            if (arg->isFloat()){
+               arg->fieldID = jenv->GetFieldID(jniContext->kernelClass, arg->name, "F");
+               arg->sizeInBytes = sizeof(jfloat);
+            }else if (arg->isInt()){
+               arg->fieldID = jenv->GetFieldID(jniContext->kernelClass, arg->name, "I");
+               arg->sizeInBytes = sizeof(jint);
+            }else if (arg->isByte()){
+               arg->fieldID = jenv->GetFieldID(jniContext->kernelClass, arg->name, "B");
+               arg->sizeInBytes = sizeof(jbyte);
+            }else if (arg->isBoolean()){
+               arg->fieldID = jenv->GetFieldID(jniContext->kernelClass, arg->name, "Z");
+               arg->sizeInBytes = sizeof(jboolean);
+            }else if (arg->isLong()){
+               arg->fieldID = jenv->GetFieldID(jniContext->kernelClass, arg->name, "J");
+               arg->sizeInBytes = sizeof(jlong);
+            }else if (arg->isDouble()){
+               arg->fieldID = jenv->GetFieldID(jniContext->kernelClass, arg->name, "D");
+               arg->sizeInBytes = sizeof(jdouble);
+            }
+         }else{ // we will use an array
+            arg->value.ref.mem = (cl_mem) 0;
+            arg->value.ref.javaArray = 0;
+            arg->sizeInBytes = 0;
+         }
+         if (jniContext->isVerbose()){
+            fprintf(stderr, "in setArgs arg %d %s type %08x\n", i, arg->name, arg->type);
+         }
+
+      }
+      // we will need an executeEvent buffer for all devices
+      jniContext->executeEvents = new cl_event[jniContext->deviceIdc];
+
+      // We will need *at most* jniContext->argc read/write events
+      jniContext->readEvents = new cl_event[jniContext->argc];
+      if (jniContext->isProfilingEnabled()) {
+         jniContext->readEventArgs = new jint[jniContext->argc];
+      }
+      jniContext->writeEvents = new cl_event[jniContext->argc];
+      if (jniContext->isProfilingEnabled()) {
+         jniContext->writeEventArgs = new jint[jniContext->argc];
+      }
+   }
+   return(status);
+}
+
+JNIEXPORT jint JNICALL Java_com_amd_aparapi_KernelRunner_getLocalSizeJNI(JNIEnv *jenv, jobject jobj, jlong jniContextHandle, jint globalSize, jint localBytesPerLocalId) {
+   size_t kernelMaxWorkGroupSize = 0;
+   size_t kernelWorkGroupSizeMultiple = 0;
+   cl_int status = CL_SUCCESS;
+   JNIContext* jniContext = JNIContext::getJNIContext(jniContextHandle);
+   if (jniContext != NULL){
+      clGetKernelWorkGroupInfo(jniContext->kernel, jniContext->deviceIds[0], CL_KERNEL_WORK_GROUP_SIZE, sizeof(kernelMaxWorkGroupSize), &kernelMaxWorkGroupSize, NULL);
+      ASSERT_CL("clGetKernelWorkGroupInfo()");
+      // starting value depends on device type
+      // not sure why the CPU has a different starting size, but it does
+      int startLocalSize = (jniContext->deviceType == CL_DEVICE_TYPE_GPU ? kernelMaxWorkGroupSize : globalSize/(jniContext->numProcessors*4));
+
+      if (startLocalSize == 0) startLocalSize = 1;
+      if (startLocalSize > kernelMaxWorkGroupSize) startLocalSize = kernelMaxWorkGroupSize;
+      if (startLocalSize > globalSize) startLocalSize = globalSize;
+      // if the kernel uses any local memory, determine our max local memory size so we can possibly limit localsize
+      cl_ulong devLocalMemSize;
+      if (localBytesPerLocalId > 0) {
+         status = clGetDeviceInfo(jniContext->deviceIds[0], CL_DEVICE_LOCAL_MEM_SIZE, sizeof(cl_ulong), &devLocalMemSize, NULL);
+         cl_uint localSizeLimitFromLocalMem = devLocalMemSize/localBytesPerLocalId;
+         if (startLocalSize > localSizeLimitFromLocalMem) startLocalSize = localSizeLimitFromLocalMem;
+         if (jniContext->isVerbose()){
+            fprintf(stderr, "localBytesPerLocalId=%d, device localMemMax=%d, localSizeLimitFromLocalMem=%d\n",
+                  localBytesPerLocalId, (cl_uint) devLocalMemSize, localSizeLimitFromLocalMem);
+         }
+
+      }
+
+      // then iterate down until we find a localSize that divides globalSize equally
+      for (int localSize = startLocalSize; localSize>0; localSize--) {
+         if (globalSize % localSize == 0) {
+            if (jniContext->isVerbose()){
+               fprintf(stderr, "for globalSize=%d, stepping localSize from %d, returning localSize=%d\n", globalSize, startLocalSize, localSize);
+            }
+            return localSize;
+         }
+      }
+   }
+   // should never get this far
+   return 0;
+}
+
+JNIEXPORT jstring JNICALL Java_com_amd_aparapi_KernelRunner_getExtensions(JNIEnv *jenv, jobject jobj, jlong jniContextHandle) {
+   jstring jextensions = NULL;
+   JNIContext* jniContext = JNIContext::getJNIContext(jniContextHandle);
+   if (jniContext != NULL){
+      size_t retvalsize = 0;
+      cl_int status = CL_SUCCESS;
+      status = clGetDeviceInfo(jniContext->deviceIds[0], CL_DEVICE_EXTENSIONS, 0, NULL, &retvalsize);
+      ASSERT_CL("clGetDeviceInfo()");
+      char* extensions = new char[retvalsize];
+      clGetDeviceInfo(jniContext->deviceIds[0], CL_DEVICE_EXTENSIONS, retvalsize, extensions, NULL);
+      jextensions = jenv->NewStringUTF(extensions);
+      delete [] extensions;
+   }
+   return jextensions;
+}
+
+// Called as a result of Kernel.get(someArray)
+JNIEXPORT jint JNICALL Java_com_amd_aparapi_KernelRunner_getJNI(JNIEnv *jenv, jobject jobj, jlong jniContextHandle, jobject buffer) {
+   cl_int status = CL_SUCCESS;
+   JNIContext* jniContext = JNIContext::getJNIContext(jniContextHandle);
+   if (jniContext != NULL){
+      jboolean foundArg = false;
+      for (jint i=0; i<jniContext->argc; i++){ 
+         KernelArg *arg= jniContext->args[i];
+         if (arg->isArray()){
+            jboolean isSame = jenv->IsSameObject(buffer, arg->value.ref.javaArray);
+            // only do this if the array that we are passed is indeed an arg we are tracking
+            if (isSame){
+               foundArg = true;
+               //fprintf(stderr, "get of %s\n", arg->name);
+
+#ifdef VERBOSE_EXPLICIT
+               fprintf(stderr, "explicitly reading buffer %d %s\n", i, arg->name);
+#endif
+               arg->pin(jenv);
+
+               status = clEnqueueReadBuffer(jniContext->commandQueues[0], arg->value.ref.mem, CL_FALSE, 0, 
+                     arg->sizeInBytes,arg->value.ref.addr , 0, NULL, &jniContext->readEvents[0]);
+               if (status != CL_SUCCESS) {
+                  PRINT_CL_ERR(status, "clEnqueueReadBuffer()");
+                  return status;
+               }
+               status = clWaitForEvents(1, jniContext->readEvents);
+               if (status != CL_SUCCESS) {
+                  PRINT_CL_ERR(status, "clWaitForEvents");
+                  return status;
+               }
+               clReleaseEvent(jniContext->readEvents[0]);
+               if (status != CL_SUCCESS) {
+                  PRINT_CL_ERR(status, "clReleaseEvent() read event");
+                  return status;
+               }
+               // since this is an explicit buffer get, we expect the buffer to have changed so we commit
+               arg->unpinCommit(jenv);
+            }
+         }
+      }
+      if (!foundArg){
+         if (jniContext->isVerbose()){
+            fprintf(stderr, "attempt to request to get a buffer that does not appear to be referenced from kernel\n");
+         }
+      }
+   }
+   return 0;
+}
+
+
+
diff --git a/com.amd.aparapi/.classpath b/com.amd.aparapi/.classpath
new file mode 100644
index 00000000..f8f3492a
--- /dev/null
+++ b/com.amd.aparapi/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src/java"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+	<classpathentry kind="output" path="classes"/>
+</classpath>
diff --git a/com.amd.aparapi/.project b/com.amd.aparapi/.project
new file mode 100644
index 00000000..54ce0fda
--- /dev/null
+++ b/com.amd.aparapi/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>com.amd.aparapi</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/com.amd.aparapi/build.xml b/com.amd.aparapi/build.xml
new file mode 100644
index 00000000..c57f0cb3
--- /dev/null
+++ b/com.amd.aparapi/build.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+
+<project name="com.amd.aparapi" default="build" basedir=".">
+
+   <target name="clean">
+      <delete dir="api"/>
+      <delete dir="classes"/>
+      <delete file="aparapi.jar"/>
+   </target>
+
+   <target name="build">
+      <mkdir dir="classes"/>
+      <javac destdir="classes" debug="on" includeAntRuntime="false" >
+         <src path="src/java"/>
+      </javac>
+      <jar jarfile="aparapi.jar" basedir="classes"/>
+   </target>
+
+</project>
diff --git a/com.amd.aparapi/noant.bat b/com.amd.aparapi/noant.bat
new file mode 100644
index 00000000..9efa2afe
--- /dev/null
+++ b/com.amd.aparapi/noant.bat
@@ -0,0 +1,88 @@
+echo off
+setlocal 
+echo removing classes and include directories
+rm -rf classes
+rm -rf include
+echo removing aparapi.jar from previous builds
+rm -rf aparapi.jar
+
+set ARCH=x86
+set ARCH=x86_64
+set SUBDIR=amd64/
+set SUBDIR2=x64/
+set HERE=%~dp0
+set CC_HOME=C:\Program Files\Microsoft Visual Studio 10.0\vc
+set CC_SDK_HOME=C:\Program Files\Microsoft SDKs\Windows\v7.0A
+set CC_IDE_HOME=C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE
+
+set CC_HOME=c:\progra~2\micros~1.0\VC
+set CC_IDE_HOME=c:\progra~2\micros~1.0\Common7\IDE
+set CC_SDK_HOME=c:\progra~1\mia713~1\windows\v6.0a
+
+
+for %%X in ("%HERE%") do set HERE=%%~sX
+for %%X in ("%JAVA_HOME%") do set JAVA_HOME=%%~sX
+for %%X in ("%ATISTREAMSDKROOT%") do set ATISTREAMSDKROOT=%%~sX
+for %%X in ("%CC_HOME%") do set CC_HOME=%%~sX
+for %%X in ("%CC_SDK_HOME%") do set CC_SDK_HOME=%%~sX
+for %%X in ("%CC_IDE_HOME%") do set CC_IDE_HOME=%%~sX
+
+
+set PATH=%PATH%;%CC_IDE_HOME%
+
+set SRC=
+
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\BranchSet.java
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\ByteBuffer.java
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\ByteReader.java
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\ClassModel.java
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\ClassParseException.java
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\ExpressionList.java
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\Instruction.java
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\InstructionPattern.java
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\InstructionSet.java
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\MethodModel.java
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\writer\BlockWriter.java
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\writer\CodeGenException.java
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\writer\InstructionHelper.java
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\writer\JavaWriter.java
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\writer\KernelWriter.java
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\writer\StringWriter.java
+set SRC=%SRC% src\java\com\amd\aparapi\classtools\writer\Table.java
+set SRC=%SRC% src\java\com\amd\aparapi\Config.java
+set SRC=%SRC% src\java\com\amd\aparapi\Kernel.java
+set SRC=%SRC% src\java\com\amd\aparapi\KernelRunner.java
+set SRC=%SRC% src\java\com\amd\aparapi\KernelUtil.java
+set SRC=%SRC% src\java\com\amd\aparapi\tools\CodeGen.java
+set SRC=%SRC% src\java\com\amd\aparapi\tools\Info.java
+ 
+echo Compiling java to classes
+mkdir classes
+%JAVA_HOME%\bin\javac -g -d classes -sourcepath src\java %SRC%
+echo Jaring classes to aparapi.jar
+%JAVA_HOME%\bin\jar -cf aparapi.jar -C classes com
+echo Creating JNI headers for com.amd.aparapi.KernelRunner in include directory
+mkdir include
+%JAVA_HOME%\bin\javah -classpath aparapi.jar -d include -force com.amd.aparapi.KernelRunner
+
+set INCS=
+set INCS=%INCS% /I%CC_HOME%\include
+set INCS=%INCS% /I%CC_SDK_HOME%\include
+set INCS=%INCS% /I%JAVA_HOME%\include
+set INCS=%INCS% /I%JAVA_HOME%\include\win32
+set INCS=%INCS% /I%HERE%\include
+set INCS=%INCS% /I%ATISTREAMSDKROOT%\include
+
+echo Compiling aparapi.cpp to aparapi.obj
+%CC_HOME%\bin\%SUBDIR%cl /nologo /TP /Ox %INCS% /c src\cpp\aparapi.cpp
+
+set LIBS=
+set LIBS=%LIBS%  /LIBPATH:%CC_HOME%\lib\%SUBDIR%
+set LIBS=%LIBS%  /LIBPATH:%CC_SDK_HOME%\lib\%SUBDIR2%
+set LIBS=%LIBS%  /LIBPATH:%ATISTREAMSDKROOT%\lib\%ARCH%
+echo Creating aparapi.dll from aparapi.obj
+%CC_HOME%\bin\cl /nologo /LD aparapi.obj /link %LIBS% OpenCL.lib /OUT:aparapi.dll
+
+echo Done
+endlocal
+
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/Annotations.java b/com.amd.aparapi/src/java/com/amd/aparapi/Annotations.java
new file mode 100644
index 00000000..39368a17
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/Annotations.java
@@ -0,0 +1,86 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+/**
+ * A collection of annotations used at dev time to tag intent.
+ * 
+ * We should be able to remove all of these before OpenSource release. 
+ * 
+ * @author gfrost
+ */
+class Annotations{
+
+   /**
+    * Use this annotation to tag stuff that needs Java Doc added. 
+    * 
+    * @author gfrost
+    */
+   @interface DocMe {
+   }
+
+   /**
+    * Use this annotation to tag fields that we think need to be removed (method/field/var).
+    * 
+    * @author gfrost
+    */
+   @interface RemoveMe {
+   }
+
+   /**
+    * Used to tag experimental features (methods/fields).  
+    * 
+    * Do not rely on anything tagged as experimental, it will probably be retracted/refactored. 
+    * 
+    * @author gfrost
+    *
+    */
+   @interface Experimental {
+   }
+
+   /**
+    * Used to tag unused features (methods/fields).  
+    * 
+    * Do not rely on anything tagged as unused, it will probably be retracted/refactored. 
+    * 
+    * @author gfrost
+    *
+    */
+   @interface Unused {
+   }
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/AparapiException.java b/com.amd.aparapi/src/java/com/amd/aparapi/AparapiException.java
new file mode 100644
index 00000000..fe652679
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/AparapiException.java
@@ -0,0 +1,64 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+/**
+ * We use <code>AparapiException</code> class and subclasses to wrap other
+ * <code>Exception</code> classes, mainly to allow differentiation between Aparapi specific issues at runtime. 
+ * 
+ * The class parser for example will throw a specific <code>ClassParseException</code> if any Aparapi unfriendly 
+ * constructs are found.  This allows us to <strong>fail fast</strong> during classfile parsing.
+ * 
+ * @see com.amd.aparapi.ClassParseException
+ * @see com.amd.aparapi.CodeGenException
+ *
+ * @author gfrost
+ *
+ */
+
+@SuppressWarnings("serial") public class AparapiException extends Exception{
+
+   AparapiException(String _msg) {
+      super(_msg);
+   }
+
+   AparapiException(Throwable _t) {
+      super(_t);
+   }
+
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/BlockWriter.java b/com.amd.aparapi/src/java/com/amd/aparapi/BlockWriter.java
new file mode 100644
index 00000000..e46728b7
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/BlockWriter.java
@@ -0,0 +1,683 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.util.Stack;
+
+import com.amd.aparapi.BranchSet.CompoundLogicalExpressionNode;
+import com.amd.aparapi.BranchSet.LogicalExpressionNode;
+import com.amd.aparapi.BranchSet.SimpleLogicalExpressionNode;
+import com.amd.aparapi.ClassModel.AttributePool.LocalVariableTableEntry.LocalVariableInfo;
+import com.amd.aparapi.ClassModel.ConstantPool.MethodEntry;
+import com.amd.aparapi.InstructionSet.AccessArrayElement;
+import com.amd.aparapi.InstructionSet.AccessField;
+import com.amd.aparapi.InstructionSet.AccessInstanceField;
+import com.amd.aparapi.InstructionSet.AccessLocalVariable;
+import com.amd.aparapi.InstructionSet.AssignToArrayElement;
+import com.amd.aparapi.InstructionSet.AssignToField;
+import com.amd.aparapi.InstructionSet.AssignToInstanceField;
+import com.amd.aparapi.InstructionSet.AssignToLocalVariable;
+import com.amd.aparapi.InstructionSet.BinaryOperator;
+import com.amd.aparapi.InstructionSet.Branch;
+import com.amd.aparapi.InstructionSet.ByteCode;
+import com.amd.aparapi.InstructionSet.CastOperator;
+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.CompositeForSunInstruction;
+import com.amd.aparapi.InstructionSet.CompositeIfElseInstruction;
+import com.amd.aparapi.InstructionSet.CompositeIfInstruction;
+import com.amd.aparapi.InstructionSet.CompositeInstruction;
+import com.amd.aparapi.InstructionSet.CompositeWhileInstruction;
+import com.amd.aparapi.InstructionSet.ConditionalBranch16;
+import com.amd.aparapi.InstructionSet.Constant;
+import com.amd.aparapi.InstructionSet.FieldArrayElementAssign;
+import com.amd.aparapi.InstructionSet.FieldArrayElementIncrement;
+import com.amd.aparapi.InstructionSet.I_ALOAD_0;
+import com.amd.aparapi.InstructionSet.I_ARRAYLENGTH;
+import com.amd.aparapi.InstructionSet.I_IINC;
+import com.amd.aparapi.InstructionSet.I_POP;
+import com.amd.aparapi.InstructionSet.If;
+import com.amd.aparapi.InstructionSet.IfUnary;
+import com.amd.aparapi.InstructionSet.IncrementInstruction;
+import com.amd.aparapi.InstructionSet.InlineAssignInstruction;
+import com.amd.aparapi.InstructionSet.MethodCall;
+import com.amd.aparapi.InstructionSet.MultiAssignInstruction;
+import com.amd.aparapi.InstructionSet.Return;
+import com.amd.aparapi.InstructionSet.UnaryOperator;
+import com.amd.aparapi.InstructionSet.VirtualMethodCall;
+
+/**
+ * Base abstract class for converting <code>Aparapi</code> IR to text.<br/>
+ * 
+ *   
+ * @author gfrost
+ *
+ */
+
+abstract class BlockWriter{
+
+   final static String arrayLengthMangleSuffix = "__javaArrayLength";
+
+   abstract void write(String _string);
+
+   protected void writeln(String _string) {
+      write(_string);
+      newLine();
+   }
+
+   private int indent = 0;
+
+   protected void in() {
+      indent++;
+   }
+
+   protected void out() {
+      indent--;
+   }
+
+   protected void newLine() {
+      write("\n");
+      for (int i = 0; i < indent; i++) {
+         write("   ");
+      }
+   }
+
+   protected void writeConditionalBranch16(ConditionalBranch16 _branch16, boolean _invert) throws CodeGenException {
+
+      if (_branch16 instanceof If) {
+         If iff = (If) _branch16;
+
+         writeInstruction(iff.getLhs());
+         write(_branch16.getOperator().getText(_invert));
+         writeInstruction(iff.getRhs());
+
+      } else if (_branch16 instanceof IfUnary) {
+         IfUnary branch16 = (IfUnary) _branch16;
+         Instruction comparison = branch16.getUnary();
+         ByteCode comparisonByteCode = comparison.getByteCode();
+         String comparisonOperator = _branch16.getOperator().getText(_invert);
+
+         switch (comparisonByteCode) {
+            case FCMPG:
+            case DCMPG:
+            case FCMPL:
+            case DCMPL:
+               if (Config.verboseComparitor)
+                  write("/* bytecode=" + comparisonByteCode.getName() + " invert=" + _invert + "*/");
+               writeInstruction(comparison.getFirstChild());
+               write(comparisonOperator);
+               writeInstruction(comparison.getLastChild());
+               break;
+            default:
+               if (Config.verboseComparitor)
+                  write("/* default bytecode=" + comparisonByteCode.getName() + " invert=" + _invert + "*/");
+               writeInstruction(comparison);
+               write(comparisonOperator);
+               write("0");
+         }
+
+      }
+
+   }
+
+   protected void writeComposite(CompositeInstruction instruction) throws CodeGenException {
+      if (instruction instanceof CompositeArbitraryScopeInstruction) {
+         newLine();
+
+         writeBlock(instruction.getFirstChild(), null);
+      } else if (instruction instanceof CompositeIfInstruction) {
+         newLine();
+         write("if (");
+         Instruction blockStart = writeConditional(((CompositeInstruction) instruction).getBranchSet());
+
+         write(")");
+         writeBlock(blockStart, null);
+      } else if (instruction instanceof CompositeIfElseInstruction) {
+         newLine();
+         write("if (");
+         Instruction blockStart = writeConditional(((CompositeInstruction) instruction).getBranchSet());
+         write(")");
+         Instruction elseGoto = blockStart;
+         while (!(elseGoto.isBranch() && elseGoto.asBranch().isUnconditional())) {
+            elseGoto = elseGoto.getNextExpr();
+         }
+         writeBlock(blockStart, elseGoto);
+         write(" else ");
+         writeBlock(elseGoto.getNextExpr(), null);
+      } else if (instruction instanceof CompositeForSunInstruction) {
+         newLine();
+         write("for (");
+         Instruction topBranch = instruction.getFirstChild();
+         if (topBranch instanceof AssignToLocalVariable) {
+            writeInstruction(topBranch);
+            topBranch = topBranch.getNextExpr();
+         }
+         write("; ");
+         BranchSet branchSet = ((CompositeInstruction) instruction).getBranchSet();
+         Instruction blockStart = writeConditional(branchSet);
+
+         Instruction lastGoto = instruction.getLastChild();
+
+         if (branchSet.getFallThrough() == lastGoto) {
+            // empty body no delta!
+            write(";){}");
+         } else {
+            Instruction delta = lastGoto.getPrevExpr();
+            write("; ");
+            if (!(delta instanceof CompositeInstruction)) {
+               writeInstruction(delta);
+               write(")");
+               writeBlock(blockStart, delta);
+            } else {
+               write("){");
+               in();
+               writeSequence(blockStart, delta);
+
+               newLine();
+               writeSequence(delta, delta.getNextExpr());
+               out();
+               newLine();
+               write("}");
+
+            }
+         }
+
+      } else if (instruction instanceof CompositeWhileInstruction) {
+         newLine();
+         write("while (");
+         BranchSet branchSet = ((CompositeInstruction) instruction).getBranchSet();
+         Instruction blockStart = writeConditional(branchSet);
+         write(")");
+         Instruction lastGoto = instruction.getLastChild();
+         writeBlock(blockStart, lastGoto);
+
+      } else if (instruction instanceof CompositeEmptyLoopInstruction) {
+         newLine();
+         write("for (");
+         Instruction topBranch = instruction.getFirstChild();
+         if (topBranch instanceof AssignToLocalVariable) {
+            writeInstruction(topBranch);
+            topBranch = topBranch.getNextExpr();
+         }
+         write("; ");
+         writeConditional(((CompositeInstruction) instruction).getBranchSet());
+         write(";){}");
+
+      } else if (instruction instanceof CompositeForEclipseInstruction) {
+         newLine();
+         write("for (");
+         Instruction topGoto = instruction.getFirstChild();
+         if (topGoto instanceof AssignToLocalVariable) {
+            writeInstruction(topGoto);
+            topGoto = topGoto.getNextExpr();
+         }
+         write("; ");
+         Instruction last = instruction.getLastChild();
+         while (last.getPrevExpr().isBranch()) {
+            last = last.getPrevExpr();
+         }
+         writeConditional(((CompositeInstruction) instruction).getBranchSet(), true);
+         write("; ");
+         Instruction delta = last.getPrevExpr();
+         if (!(delta instanceof CompositeInstruction)) {
+            writeInstruction(delta);
+            write(")");
+            writeBlock(topGoto.getNextExpr(), delta);
+         } else {
+            write("){");
+            in();
+            writeSequence(topGoto.getNextExpr(), delta);
+
+            newLine();
+            writeSequence(delta, delta.getNextExpr());
+            out();
+            newLine();
+            write("}");
+
+         }
+      }
+   }
+
+   protected void writeSequence(Instruction _first, Instruction _last) throws CodeGenException {
+
+      for (Instruction instruction = _first; instruction != _last; instruction = instruction.getNextExpr()) {
+         if (instruction instanceof CompositeInstruction) {
+            writeComposite((CompositeInstruction) instruction);
+         } else if (!instruction.getByteCode().equals(ByteCode.NONE)) {
+            newLine();
+            writeInstruction(instruction);
+            write(";");
+
+         }
+      }
+
+   }
+
+   protected void writeBlock(Instruction _first, Instruction _last) throws CodeGenException {
+      write("{");
+      in();
+      writeSequence(_first, _last);
+      out();
+      newLine();
+
+      write("}");
+   }
+
+   protected Instruction writeConditional(BranchSet _branchSet) throws CodeGenException {
+      return (writeConditional(_branchSet, false));
+   }
+
+   protected Instruction writeConditional(BranchSet _branchSet, boolean _invert) throws CodeGenException {
+
+      LogicalExpressionNode logicalExpression = _branchSet.getLogicalExpression();
+      if (!_invert) {
+         logicalExpression.invert();
+      }
+      write(logicalExpression);
+      return (_branchSet.getLast().getNextExpr());
+   }
+
+   protected void write(LogicalExpressionNode _node) throws CodeGenException {
+      if (_node instanceof SimpleLogicalExpressionNode) {
+         SimpleLogicalExpressionNode sn = (SimpleLogicalExpressionNode) _node;
+
+         writeConditionalBranch16((ConditionalBranch16) sn.getBranch(), sn.isInvert());
+      } else {
+         CompoundLogicalExpressionNode ln = (CompoundLogicalExpressionNode) _node;
+         boolean needParenthesis = false;
+         CompoundLogicalExpressionNode parent = (CompoundLogicalExpressionNode) ln.getParent();
+         if (parent != null) {
+            if (!ln.isAnd() && parent.isAnd()) {
+               needParenthesis = true;
+            }
+         }
+         if (needParenthesis) {
+
+            write("(");
+         }
+         write(ln.getLhs());
+         write(ln.isAnd() ? " && " : " || ");
+         write(ln.getRhs());
+         if (needParenthesis) {
+
+            write(")");
+         }
+      }
+   }
+
+   protected String convertType(String _typeDesc, boolean useClassModel) {
+      return (_typeDesc);
+   }
+
+   protected String convertCast(String _cast) {
+      // Strip parens off cast
+      //System.out.println("cast = " + _cast);
+      String raw = convertType(_cast.substring(1, _cast.length() - 1), false);
+      return ("(" + raw + ")");
+   }
+
+   void writeInstruction(Instruction _instruction) throws CodeGenException {
+      if (_instruction instanceof CompositeIfElseInstruction) {
+         write("(");
+         Instruction lhs = writeConditional(((CompositeInstruction) _instruction).getBranchSet());
+         write(")?");
+         writeInstruction(lhs);
+         write(":");
+         writeInstruction(lhs.getNextExpr().getNextExpr());
+      } else if (_instruction instanceof CompositeInstruction) {
+         writeComposite((CompositeInstruction) _instruction);
+
+      } else if (_instruction instanceof AssignToLocalVariable) {
+         AssignToLocalVariable assignToLocalVariable = (AssignToLocalVariable) _instruction;
+
+         LocalVariableInfo localVariableInfo = assignToLocalVariable.getLocalVariableInfo();
+         if (assignToLocalVariable.isDeclaration()) {
+            String descriptor = localVariableInfo.getVariableDescriptor();
+            // Arrays always map to __global arrays
+            if (descriptor.startsWith("[")) {
+               write(" __global ");
+            }
+            write(convertType(descriptor, true));
+         }
+         if (localVariableInfo == null) {
+            throw new CodeGenException("outOfScope" + _instruction.getThisPC() + " = ");
+         } else {
+            write(localVariableInfo.getVariableName() + " = ");
+         }
+
+         for (Instruction operand = _instruction.getFirstChild(); operand != null; operand = operand.getNextExpr()) {
+            writeInstruction(operand);
+         }
+
+      } else if (_instruction instanceof AssignToArrayElement) {
+         AssignToArrayElement arrayAssignmentInstruction = (AssignToArrayElement) _instruction;
+         writeInstruction(arrayAssignmentInstruction.getArrayRef());
+         write("[");
+         writeInstruction(arrayAssignmentInstruction.getArrayIndex());
+         write("]");
+         write(" ");
+         write(" = ");
+         writeInstruction(arrayAssignmentInstruction.getValue());
+      } else if (_instruction instanceof AccessArrayElement) {
+         AccessArrayElement arrayLoadInstruction = (AccessArrayElement) _instruction;
+         writeInstruction(arrayLoadInstruction.getArrayRef());
+         write("[");
+         writeInstruction(arrayLoadInstruction.getArrayIndex());
+         write("]");
+      } else if (_instruction instanceof AccessField) {
+         AccessField accessField = (AccessField) _instruction;
+         if (accessField instanceof AccessInstanceField) {
+            Instruction accessInstanceField = ((AccessInstanceField) accessField).getInstance();
+            if (accessInstanceField instanceof CloneInstruction) {
+               accessInstanceField = ((CloneInstruction) accessInstanceField).getReal();
+            }
+            if (!(accessInstanceField instanceof I_ALOAD_0)) {
+               writeInstruction(accessInstanceField);
+               write(".");
+            } else {
+               writeThisRef();
+            }
+         }
+         write(accessField.getConstantPoolFieldEntry().getNameAndTypeEntry().getNameUTF8Entry().getUTF8());
+
+      } else if (_instruction instanceof I_ARRAYLENGTH) {
+         AccessInstanceField child = (AccessInstanceField) _instruction.getFirstChild();
+         String arrayName = child.getConstantPoolFieldEntry().getNameAndTypeEntry().getNameUTF8Entry().getUTF8();
+         write("this->" + arrayName + arrayLengthMangleSuffix);
+      } else if (_instruction instanceof AssignToField) {
+         AssignToField assignedField = (AssignToField) _instruction;
+
+         if (assignedField instanceof AssignToInstanceField) {
+            Instruction accessInstanceField = ((AssignToInstanceField) assignedField).getInstance().getReal();
+
+            if (!(accessInstanceField instanceof I_ALOAD_0)) {
+               writeInstruction(accessInstanceField);
+               write(".");
+            } else {
+               writeThisRef();
+            }
+         }
+         write(assignedField.getConstantPoolFieldEntry().getNameAndTypeEntry().getNameUTF8Entry().getUTF8());
+         write("=");
+         writeInstruction(assignedField.getValueToAssign());
+      } else if (_instruction instanceof I_ALOAD_0) {
+         write("this");
+      } else if (_instruction instanceof Constant<?>) {
+         Constant<?> constantInstruction = (Constant<?>) _instruction;
+         Object value = constantInstruction.getValue();
+         write(value.toString());
+         if (value instanceof Float) {
+            write("f");
+         }
+         if (value instanceof Long) {
+            write("L");
+         }
+
+      } else if (_instruction instanceof AccessLocalVariable) {
+         AccessLocalVariable localVariableLoadInstruction = (AccessLocalVariable) _instruction;
+         LocalVariableInfo localVariable = localVariableLoadInstruction.getLocalVariableInfo();
+         write(localVariable.getVariableName());
+      } else if (_instruction instanceof I_IINC) {
+         I_IINC location = (I_IINC) _instruction;
+         LocalVariableInfo localVariable = location.getLocalVariableInfo();
+         int adjust = location.getAdjust();
+
+         write(localVariable.getVariableName());
+         if (adjust == 1) {
+            write("++");
+         } else if (adjust == -1) {
+            write("--");
+         } else if (adjust > 1) {
+            write("+=" + adjust);
+         } else if (adjust < -1) {
+            write("-=" + (-adjust));
+         }
+      } else if (_instruction instanceof BinaryOperator) {
+         BinaryOperator binaryInstruction = (BinaryOperator) _instruction;
+         Instruction parent = binaryInstruction.getParentExpr();
+         boolean needsParenthesis = true;
+
+         if (parent instanceof AssignToLocalVariable) {
+            needsParenthesis = false;
+         } else if (parent instanceof AssignToField) {
+            needsParenthesis = false;
+         } else if (parent instanceof AssignToArrayElement) {
+            needsParenthesis = false;
+         } else {
+            /**
+                        if (parent instanceof BinaryOperator) {
+                           BinaryOperator parentBinaryOperator = (BinaryOperator) parent;
+                           if (parentBinaryOperator.getOperator().ordinal() > binaryInstruction.getOperator().ordinal()) {
+                              needsParenthesis = false;
+                           }
+                        }
+            **/
+         }
+
+         if (needsParenthesis) {
+            write("(");
+         }
+
+         writeInstruction(binaryInstruction.getLhs());
+
+         write(" " + binaryInstruction.getOperator().getText() + " ");
+         writeInstruction(binaryInstruction.getRhs());
+
+         if (needsParenthesis) {
+            write(")");
+         }
+
+      } else if (_instruction instanceof CastOperator) {
+         CastOperator castInstruction = (CastOperator) _instruction;
+         //  write("(");
+         write(convertCast(castInstruction.getOperator().getText()));
+
+         writeInstruction(castInstruction.getUnary());
+         //    write(")");
+      } else if (_instruction instanceof UnaryOperator) {
+         UnaryOperator unaryInstruction = (UnaryOperator) _instruction;
+         //   write("(");
+         write(unaryInstruction.getOperator().getText());
+
+         writeInstruction(unaryInstruction.getUnary());
+         //   write(")");
+      } else if (_instruction instanceof Return) {
+
+         Return ret = (Return) _instruction;
+         write("return");
+         if (ret.getStackConsumeCount() > 0) {
+            write("(");
+            writeInstruction(ret.getFirstChild());
+            write(")");
+         }
+
+      } else if (_instruction instanceof MethodCall) {
+         MethodCall methodCall = (MethodCall) _instruction;
+
+         MethodEntry methodEntry = methodCall.getConstantPoolMethodEntry();
+
+         writeMethod(methodCall, methodEntry);
+      } else if (_instruction.getByteCode().equals(ByteCode.CLONE)) {
+         CloneInstruction cloneInstruction = (CloneInstruction) _instruction;
+         writeInstruction(cloneInstruction.getReal());
+      } else if (_instruction.getByteCode().equals(ByteCode.INCREMENT)) {
+         IncrementInstruction incrementInstruction = (IncrementInstruction) _instruction;
+
+         if (incrementInstruction.isPre()) {
+            if (incrementInstruction.isInc()) {
+               write("++");
+            } else {
+               write("--");
+            }
+         }
+
+         writeInstruction(incrementInstruction.getFieldOrVariableReference());
+         if (!incrementInstruction.isPre()) {
+            if (incrementInstruction.isInc()) {
+               write("++");
+            } else {
+               write("--");
+            }
+         }
+      } else if (_instruction.getByteCode().equals(ByteCode.MULTI_ASSIGN)) {
+         MultiAssignInstruction multiAssignInstruction = (MultiAssignInstruction) _instruction;
+         AssignToLocalVariable from = (AssignToLocalVariable) multiAssignInstruction.getFrom();
+         AssignToLocalVariable last = (AssignToLocalVariable) multiAssignInstruction.getTo();
+         Instruction common = multiAssignInstruction.getCommon();
+         Stack<AssignToLocalVariable> stack = new Stack<AssignToLocalVariable>();
+
+         while (from != last) {
+            stack.push(from);
+            from = (AssignToLocalVariable) ((Instruction) from).getNextExpr();
+         }
+
+         for (AssignToLocalVariable alv = stack.pop(); alv != null; alv = stack.size() > 0 ? stack.pop() : null) {
+
+            LocalVariableInfo localVariableInfo = alv.getLocalVariableInfo();
+            if (alv.isDeclaration()) {
+               write(convertType(localVariableInfo.getVariableDescriptor(), true));
+            }
+            if (localVariableInfo == null) {
+               throw new CodeGenException("outOfScope" + _instruction.getThisPC() + " = ");
+            } else {
+               write(localVariableInfo.getVariableName() + " = ");
+            }
+
+         }
+         writeInstruction(common);
+      } else if (_instruction.getByteCode().equals(ByteCode.INLINE_ASSIGN)) {
+         InlineAssignInstruction inlineAssignInstruction = (InlineAssignInstruction) _instruction;
+         AssignToLocalVariable assignToLocalVariable = inlineAssignInstruction.getAssignToLocalVariable();
+
+         LocalVariableInfo localVariableInfo = assignToLocalVariable.getLocalVariableInfo();
+         if (assignToLocalVariable.isDeclaration()) {
+            // this is bad! we need a general way to hoist up a required declaration
+            throw new CodeGenException("/* we can't declare this " + convertType(localVariableInfo.getVariableDescriptor(), true)
+                  + " here */");
+         }
+         write(localVariableInfo.getVariableName());
+         write("=");
+         writeInstruction(inlineAssignInstruction.getRhs());
+      } else if (_instruction.getByteCode().equals(ByteCode.FIELD_ARRAY_ELEMENT_ASSIGN)) {
+         FieldArrayElementAssign inlineAssignInstruction = (FieldArrayElementAssign) _instruction;
+         AssignToArrayElement arrayAssignmentInstruction = inlineAssignInstruction.getAssignToArrayElement();
+
+         writeInstruction(arrayAssignmentInstruction.getArrayRef());
+         write("[");
+         writeInstruction(arrayAssignmentInstruction.getArrayIndex());
+         write("]");
+         write(" ");
+         write(" = ");
+
+         writeInstruction(inlineAssignInstruction.getRhs());
+      } else if (_instruction.getByteCode().equals(ByteCode.FIELD_ARRAY_ELEMENT_INCREMENT)) {
+
+         FieldArrayElementIncrement fieldArrayElementIncrement = (FieldArrayElementIncrement) _instruction;
+         AssignToArrayElement arrayAssignmentInstruction = fieldArrayElementIncrement.getAssignToArrayElement();
+         if (fieldArrayElementIncrement.isPre()) {
+            if (fieldArrayElementIncrement.isInc()) {
+               write("++");
+            } else {
+               write("--");
+            }
+         }
+         writeInstruction(arrayAssignmentInstruction.getArrayRef());
+
+         write("[");
+         writeInstruction(arrayAssignmentInstruction.getArrayIndex());
+         write("]");
+         if (!fieldArrayElementIncrement.isPre()) {
+            if (fieldArrayElementIncrement.isInc()) {
+               write("++");
+            } else {
+               write("--");
+            }
+         }
+
+      } else if (_instruction.getByteCode().equals(ByteCode.NONE)) {
+         // we are done
+      } else if (_instruction instanceof Branch) {
+         throw new CodeGenException(String.format("%s -> %04d", _instruction.getByteCode().toString().toLowerCase(),
+               ((Branch) _instruction).getTarget().getThisPC()));
+      } else if (_instruction instanceof I_POP) {
+         //POP discarded void call return?
+         writeInstruction(_instruction.getFirstChild());
+      } else {
+         throw new CodeGenException(String.format("%s", _instruction.getByteCode().toString().toLowerCase()));
+      }
+
+   }
+
+   protected void writeMethod(MethodCall _methodCall, MethodEntry _methodEntry) throws CodeGenException {
+
+      if (_methodCall instanceof VirtualMethodCall) {
+         Instruction instanceInstruction = ((VirtualMethodCall) _methodCall).getInstanceReference();
+         if (!(instanceInstruction instanceof I_ALOAD_0)) {
+            writeInstruction(instanceInstruction);
+            write(".");
+         } else {
+            writeThisRef();
+         }
+      }
+      int argc = _methodEntry.getStackConsumeCount();
+      write(_methodEntry.getNameAndTypeEntry().getNameUTF8Entry().getUTF8());
+      write("(");
+
+      for (int arg = 0; arg < argc; arg++) {
+         if (arg != 0) {
+            write(", ");
+         }
+         writeInstruction(_methodCall.getArg(arg));
+      }
+      write(")");
+
+   }
+
+   protected void writeThisRef() {
+      write("this.");
+   }
+
+   protected void writeMethodBody(MethodModel _methodModel) throws CodeGenException {
+      writeBlock(_methodModel.getExprHead(), null);
+   }
+
+   abstract void write(Entrypoint entryPoint) throws CodeGenException;
+
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/BranchSet.java b/com.amd.aparapi/src/java/com/amd/aparapi/BranchSet.java
new file mode 100644
index 00000000..5d807c71
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/BranchSet.java
@@ -0,0 +1,372 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import com.amd.aparapi.InstructionSet.Branch;
+import com.amd.aparapi.InstructionSet.ConditionalBranch;
+
+/**
+ * Deals with the issue of recognizing that a sequence of bytecode branch instructions actually represent a single if/while with a logical expression.
+ * 
+ * <p>
+ * A logical expressions such as
+ * <pre><code>
+      if (i>= 0 && i%2 == 0 && i<100){}
+ * </code></pre>
+ * gets translated into a sequence of bytecode level branches and targets.  Which might look like the following. 
+ * <pre><code>
+   a: if ? e      +
+   b: if ? d      |+
+   c: if ? e      ||+
+   d: if ? out    |v|+
+   e: ...         v v|
+      ...            |
+ out: _instruction   v
+ * </code></pre>
+ * We need an algorithm for recognizing the underlying logical expression. 
+ * <p>
+ * Essentially, given a set of branches, get the longest sequential sequence including the input set which target each other or _target.
+ *
+ * Branches can legally branch to another in the valid set, or to the fall through of the last in the valid set or to _target
+ *<p>
+ * So an <pre>if(COND){IF_INSTRUCTIONS}else{ELSE_INSTUCTIONS}...</pre> will be  
+<pre><code> 
+       branch[?? branch]*, instructions*,goto,instruction*,target
+</code></pre>
+ * and <pre>if(COND){IF_INSTRUCTIONS}...</pre> will be :-
+<code><pre>
+       branch[?? branch]*,instruction*,target
+</pre></code>
+ *  The psuedo code code the algorithm looks like this:
+<code><pre>
+   int n=0;
+   while (exp.length >1){
+     if (exp[n].target == exp[n+1].target){          #rule 1
+      replace exp[n] and exp[n+1] with a single expression representing 'exp[n] || exp[n+1]'
+      n=0;
+     }else if (exp[n].target == exp[n+1].next){      #rule 2
+      replace exp[n] and exp[n+1] with a single expression representing '!(exp[n]) && exp[n+1]
+      n=0;
+     }else{                                          #rule 3
+      n++;
+     }
+   }
+
+   result = !exp[0];
+</pre></code>
+ * @author gfrost 
+ */
+
+class BranchSet{
+   /**
+    * Base abstract class used to hold information used to construct node tree for logical expressions. 
+    * 
+    * @see SimpleLogicalExpressionNode
+    * @see CompoundLogicalExpressionNode
+    * 
+    * @author gfrost
+    *
+    */
+   static abstract class LogicalExpressionNode{
+      private LogicalExpressionNode next = null;
+
+      private LogicalExpressionNode parent = null;
+
+      void setParent(LogicalExpressionNode _parent) {
+         parent = _parent;
+      }
+
+      abstract int getTarget();
+
+      abstract int getFallThrough();
+
+      abstract void invert();
+
+      LogicalExpressionNode getRoot() {
+         if (parent != null) {
+            return (parent);
+         } else {
+            return (this);
+         }
+      }
+
+      LogicalExpressionNode getNext() {
+         return (next == null ? next : next.getRoot());
+      }
+
+      void setNext(LogicalExpressionNode _next) {
+         next = _next == null ? _next : _next.getRoot();
+      }
+
+      LogicalExpressionNode getParent() {
+         return (parent);
+      }
+   }
+
+   /**
+    * A node in the expression tree representing a simple logical expression.
+    * 
+    * For example <bold><code>(i&lt3)</code></bold> in the following would appear as a SimpleLogicalExpressionNode<br/>
+    * <pre><code>
+    * if (i<3){}
+    * </code></pre>
+    * 
+    * @author gfrost
+    *
+    */
+   static class SimpleLogicalExpressionNode extends LogicalExpressionNode{
+      private ConditionalBranch branch;
+
+      protected boolean invert = false;
+
+      SimpleLogicalExpressionNode(ConditionalBranch _branch) {
+         branch = _branch;
+      }
+
+      @Override int getTarget() {
+         return (getBranch().getTarget().getThisPC());
+      }
+
+      @Override void invert() {
+         invert = !invert;
+      }
+
+      @Override int getFallThrough() {
+         return (getBranch().getNextPC().getThisPC());
+      }
+
+      boolean isInvert() {
+         return (invert);
+      }
+
+      ConditionalBranch getBranch() {
+         return branch;
+      }
+
+   }
+
+   /**
+    * A node in the expression tree representing a simple logical expression.
+    * 
+    * For example <bold><code>(i&lt3 || i&gt10)</code></bold> in the following would appear as a CompoundLogicalExpressionNode<br/>
+    * <pre><code>
+    * if (i<3 || i>10){}
+    * </code></pre>
+    * 
+    * @author gfrost
+    *
+    */
+   static class CompoundLogicalExpressionNode extends LogicalExpressionNode{
+      private LogicalExpressionNode lhs;
+
+      private LogicalExpressionNode rhs;
+
+      private boolean and;
+
+      CompoundLogicalExpressionNode(boolean _and, LogicalExpressionNode _lhs, LogicalExpressionNode _rhs) {
+         lhs = _lhs;
+         and = _and;
+         rhs = _rhs;
+         setNext(_rhs.getNext());
+         if (and) {
+            lhs.invert();
+            // rhs.invert();
+         }
+         rhs.setParent(this);
+         lhs.setParent(this);
+      }
+
+      @Override int getTarget() {
+         return (rhs.getTarget());
+      }
+
+      @Override void invert() {
+         and = !and;
+         lhs.invert();
+         rhs.invert();
+      }
+
+      boolean isAnd() {
+         return (and);
+      }
+
+      @Override int getFallThrough() {
+         return (rhs.getFallThrough());
+      }
+
+      LogicalExpressionNode getLhs() {
+
+         return lhs;
+      }
+
+      LogicalExpressionNode getRhs() {
+
+         return rhs;
+      }
+   }
+
+   private List<ConditionalBranch> set = new ArrayList<ConditionalBranch>();
+
+   private Instruction fallThrough;
+
+   private Instruction target;
+
+   private Branch last;
+
+   private Branch first;
+
+   private LogicalExpressionNode logicalExpressionNode = null;
+
+   /**
+    * We construct a branch set with the 'last' branch.  It is assumed that all nodes prior to <code>_branch</code> are folded.
+    * 
+    * This will walk backwards until it finds a non-branch or until it finds a branch that does not below to this set.
+    * 
+    * @param _branch
+    */
+   BranchSet(Branch _branch) {
+      target = _branch.getTarget();
+      last = _branch;
+
+      Set<Branch> expandedSet = new LinkedHashSet<Branch>();
+      Instruction fallThroughRoot = last.getNextExpr();
+      fallThrough = fallThroughRoot == null ? last.getNextPC() : fallThroughRoot.getStartInstruction();
+      first = last;
+      while (first.getPrevExpr() != null && first.getPrevExpr().isBranch() && first.getPrevExpr().asBranch().isConditional()) {
+         Instruction prevBranchTarget = first.getPrevExpr().asBranch().getTarget();
+         Instruction prevBranchTargetRoot = prevBranchTarget.getRootExpr();
+         if (prevBranchTarget == target || prevBranchTarget == fallThrough || expandedSet.contains(prevBranchTargetRoot)) {
+            expandedSet.add(first);
+            first = first.getPrevExpr().asBranch();
+         } else {
+            break;
+         }
+      }
+      for (Instruction i = first; i != fallThroughRoot; i = i.getNextExpr()) {
+         set.add((ConditionalBranch) i.asBranch());
+         ((ConditionalBranch) i.asBranch()).setBranchSet(this);
+      }
+
+      //   ConditionalBranch16 branches[] = set.toArray(new ConditionalBranch16[0]);
+
+      LogicalExpressionNode end = null;
+      for (ConditionalBranch cb : set) {
+         SimpleLogicalExpressionNode sn = new SimpleLogicalExpressionNode(cb);
+         if (logicalExpressionNode == null) {
+            logicalExpressionNode = sn;
+         } else {
+            end.setNext(sn);
+         }
+         end = sn;
+      }
+      int count = 0;
+      while (logicalExpressionNode.next != null) {
+         if (++count > 20) {
+            throw new IllegalStateException("Sanity check, we seem to have >20 iterations collapsing logical expression");
+         }
+         LogicalExpressionNode n = logicalExpressionNode;
+         LogicalExpressionNode prev = null;
+         int i = 0;
+
+         while (n != null && n.getNext() != null) {
+            if (n.getTarget() == n.getNext().getTarget() || n.getTarget() == n.getNext().getFallThrough()) {
+               LogicalExpressionNode newNode = null;
+               if (n.getTarget() == n.getNext().getTarget()) {
+                  // lhs(n) and rhs(n.next) are branching to the same location so we replace (lhs ?? rhs) with (lhs || rhs)
+                  // System.out.println("exp["+i+"] exp["+(i+1)+"] replaced by (exp["+i+"] || exp["+(i+1)+"])");
+                  newNode = new CompoundLogicalExpressionNode(false, n, n.getNext());
+               } else if (n.getTarget() == n.getNext().getFallThrough()) {
+                  // lhs(n) target and rhs(n.next) fallthrough are the same so we replace (lhs ?? rhs) with !(lhs && rhs)
+                  // System.out.println("exp["+i+"] exp["+(i+1)+"] replaced by (!exp["+i+"] && exp["+(i+1)+"])");
+                  newNode = new CompoundLogicalExpressionNode(true, n, n.getNext());
+               }
+               if (n == logicalExpressionNode) {
+                  logicalExpressionNode = newNode;
+               }
+               if (prev != null) {
+                  prev.setNext(newNode);
+               }
+               break;
+            } else {
+               prev = n;
+               n = n.getNext();
+               i++;
+            }
+         }
+
+      }
+
+   }
+
+   List<ConditionalBranch> getBranches() {
+      return (set);
+   }
+
+   Branch getFirst() {
+      return (first);
+   }
+
+   Branch getLast() {
+
+      return (last);
+   }
+
+   void unhook() {
+      for (Branch b : set) {
+         b.unhook();
+      }
+   }
+
+   Instruction getTarget() {
+      return (target);
+   }
+
+   Instruction getFallThrough() {
+      return (fallThrough);
+   }
+
+   LogicalExpressionNode getLogicalExpression() {
+      return (logicalExpressionNode);
+
+   }
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/ByteBuffer.java b/com.amd.aparapi/src/java/com/amd/aparapi/ByteBuffer.java
new file mode 100644
index 00000000..ea323bbf
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/ByteBuffer.java
@@ -0,0 +1,225 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Used to parse ClassFile structure. <br/>
+ * 
+ * Provides low level access to sequential bytes in a stream given a specific offset.
+ * 
+ * Does not keep track of accesses.  For this you will need a <code>ByteReader</code>
+ * 
+ * @see com.amd.aparapi.ByteReader
+ * 
+ * @author gfrost
+ *
+ */
+class ByteBuffer{
+
+   private byte[] bytes;
+
+   /**
+    * Construct from an <code>InputStream</code>
+    * 
+    * @param _inputStream
+    */
+   ByteBuffer(InputStream _inputStream) {
+
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      bytes = new byte[4096];
+      int bytesRead = 0;
+      try {
+         while ((bytesRead = _inputStream.read(bytes)) > 0) {
+            baos.write(bytes, 0, bytesRead);
+         }
+         bytes = baos.toByteArray();
+      } catch (IOException e) {
+         bytes = new byte[0];
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+
+   }
+
+   int u2(int _offset) {
+      return (u1(_offset) << 8 | u1(_offset + 1));
+   }
+
+   int s2(int _offset) {
+      int s2 = u2(_offset);
+
+      if (s2 > 0x7fff) {
+         s2 = -(0x10000 - s2);
+      }
+      return (s2);
+   }
+
+   int u4(int _offset) {
+      return (u2(_offset) << 16 | u2(_offset + 2));
+   }
+
+   int s4(int _offset) {
+      int s4 = u4(_offset);
+      return (s4);
+   }
+
+   ByteBuffer(byte[] _bytes) {
+      bytes = _bytes;
+   }
+
+   int u1(int _offset) {
+      return ((bytes[_offset] & 0xff));
+   }
+
+   int size() {
+      return (bytes.length);
+   }
+
+   double d8(int _offset) {
+      return (Double.longBitsToDouble(u8(_offset)));
+   }
+
+   float f4(int _offset) {
+      return (Float.intBitsToFloat(u4(_offset)));
+
+   }
+
+   long u8(int _offset) {
+      return (((long) u4(_offset)) << 32 | u4(_offset + 4));
+   }
+
+   int utf8bytes(int _offset) {
+      return (2 + u2(_offset));
+   }
+
+   byte[] bytes(int _offset, int _length) {
+      byte[] returnBytes = new byte[_length];
+      System.arraycopy(bytes, _offset, returnBytes, 0, _length);
+      return (returnBytes);
+   }
+
+   // See DataInputStream utf8, that's where we liberated this from
+   String utf8(int _offset) {
+      int utflen = u2(_offset);
+      _offset += 2;
+      byte[] bytearr = new byte[utflen];
+      char[] chararr = new char[utflen];
+
+      int c, char2, char3;
+      int count = 0;
+      int chararr_count = 0;
+
+      for (int i = 0; i < utflen; i++) {
+         bytearr[i] = b(_offset + i);
+      }
+      _offset += utflen;
+
+      while (count < utflen) {
+         c = bytearr[count] & 0xff;
+         if (c > 127)
+            break;
+         count++;
+         chararr[chararr_count++] = (char) c;
+      }
+
+      while (count < utflen) {
+         c = bytearr[count] & 0xff;
+         switch (c >> 4) {
+            case 0:
+            case 1:
+            case 2:
+            case 3:
+            case 4:
+            case 5:
+            case 6:
+            case 7:
+               /* 0xxxxxxx*/
+               count++;
+               chararr[chararr_count++] = (char) c;
+               break;
+            case 12:
+            case 13:
+               /* 110x xxxx   10xx xxxx*/
+               count += 2;
+               if (count > utflen) {
+                  System.out.println("malformed input: partial character at end");
+                  return (null);
+               }
+               char2 = bytearr[count - 1];
+               if ((char2 & 0xC0) != 0x80) {
+                  System.out.println("malformed input around byte " + count);
+                  return (null);
+               }
+               chararr[chararr_count++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
+               break;
+            case 14:
+               /* 1110 xxxx  10xx xxxx  10xx xxxx */
+               count += 3;
+               if (count > utflen) {
+                  System.out.println("malformed input: partial character at end");
+                  return (null);
+               }
+               char2 = bytearr[count - 2];
+               char3 = bytearr[count - 1];
+               if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) {
+                  System.out.println("malformed input around byte " + (count - 1));
+                  return (null);
+               }
+               chararr[chararr_count++] = (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
+               break;
+            default:
+               /* 10xx xxxx,  1111 xxxx */
+               System.out.println("malformed input around byte " + count);
+               return (null);
+         }
+      }
+      // The number of chars produced may be less than utflen
+      String returnString = new String(chararr, 0, chararr_count);
+      // System.out.println("returnString.length="+returnString.length()+" byte[]="+bytearr.length);
+      return (returnString);
+   }
+
+   byte b(int _offset) {
+      return bytes[_offset];
+   }
+
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/ByteReader.java b/com.amd.aparapi/src/java/com/amd/aparapi/ByteReader.java
new file mode 100644
index 00000000..3fae782e
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/ByteReader.java
@@ -0,0 +1,165 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.io.InputStream;
+
+/**
+ * Primarily used to parse various ClassFile structures. This class provides low level access to sequential bytes in a stream given stream.
+ * <p>
+ * Basically wraps a <code>ByteBuffer</code> and keeps track of the current offset. All requests on 
+ * this <code>ByteReader</code> will be delegated to wrapped<code>ByteBuffer</code>.
+ * </p>
+ * @see com.amd.aparapi.ByteBuffer
+ * 
+ * @author gfrost
+ *
+ */
+class ByteReader{
+   private final ByteBuffer byteBuffer;
+
+   private int offset;
+
+   /**
+    * Construct form a given ByteBuffer.
+    * 
+    * @param _byteBuffer an existing <code>ByteBuffer</code>
+    */
+   ByteReader(ByteBuffer _byteBuffer) {
+      byteBuffer = _byteBuffer;
+   }
+
+   /**
+    * Construct form an array of bytes.
+    * 
+    * @param _bytes an existing byte array
+    */
+   ByteReader(byte[] _bytes) {
+      this(new ByteBuffer(_bytes));
+   }
+
+   /**
+    * Construct form an input stream (say a ClassFile).
+    * 
+    * @param _inputStream a stream of bytes
+    */
+   ByteReader(InputStream _inputStream) {
+      this(new ByteBuffer(_inputStream));
+   }
+
+   int u1() {
+      int value = byteBuffer.u1(offset);
+      offset += 1;
+      return (value);
+   }
+
+   int u2() {
+      int value = byteBuffer.u2(offset);
+      offset += 2;
+      return (value);
+   }
+
+   int s2() {
+      int value = byteBuffer.s2(offset);
+      offset += 2;
+      return (value);
+   }
+
+   int peekU2() {
+      return (byteBuffer.u2(offset));
+   }
+
+   int u4() {
+      int value = byteBuffer.u4(offset);
+      offset += 4;
+      return (value);
+   }
+
+   int s4() {
+      int value = byteBuffer.s4(offset);
+      offset += 4;
+      return (value);
+   }
+
+   long u8() {
+      long value = byteBuffer.u8(offset);
+      offset += 8;
+      return (value);
+   }
+
+   float f4() {
+      float value = byteBuffer.f4(offset);
+      offset += 4;
+      return (value);
+   }
+
+   double d8() {
+      double value = byteBuffer.d8(offset);
+      offset += 8;
+      return (value);
+   }
+
+   String utf8() {
+      String utf8 = byteBuffer.utf8(offset);
+      offset += byteBuffer.utf8bytes(offset);
+      return (utf8);
+   }
+
+   byte[] bytes(int _length) {
+      byte[] bytes = byteBuffer.bytes(offset, _length);
+      offset += _length;
+      return (bytes);
+   }
+
+   void skip(int _length) {
+      offset += _length;
+   }
+
+   int getOffset() {
+      return (offset);
+   }
+
+   void setOffset(int _offset) {
+      offset = _offset;
+   }
+
+   boolean hasMore() {
+      return (getOffset() < byteBuffer.size());
+   }
+
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/ClassModel.java b/com.amd.aparapi/src/java/com/amd/aparapi/ClassModel.java
new file mode 100644
index 00000000..b74c59c5
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/ClassModel.java
@@ -0,0 +1,2388 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.amd.aparapi.ClassModel.AttributePool.CodeEntry;
+import com.amd.aparapi.ClassModel.AttributePool.LocalVariableTableEntry;
+import com.amd.aparapi.ClassModel.ConstantPool.FieldEntry;
+import com.amd.aparapi.ClassModel.ConstantPool.MethodEntry;
+import com.amd.aparapi.InstructionSet.TypeSpec;
+
+/**
+ * Class represents a ClassFile (MyClass.class).
+ * 
+ * A ClassModel is constructed from an instance of a <code>java.lang.Class</code>.
+ * 
+ * If the java class mode changes we may need to modify this to accommodate.
+ * 
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/ClassFileFormat-Java5.pdf">Java 5 Class File Format</a>
+ * 
+ * @author gfrost
+ *
+ */
+class ClassModel{
+
+   static final char SIGC_VOID = 'V';
+
+   static final char SIGC_BOOLEAN = 'Z';
+
+   static final char SIGC_BYTE = 'B';
+
+   static final char SIGC_CHAR = 'C';
+
+   static final char SIGC_SHORT = 'S';
+
+   static final char SIGC_INT = 'I';
+
+   static final char SIGC_LONG = 'J';
+
+   static final char SIGC_FLOAT = 'F';
+
+   static final char SIGC_DOUBLE = 'D';
+
+   static final char SIGC_ARRAY = '[';
+
+   static final char SIGC_CLASS = 'L';
+
+   static final char SIGC_START_METHOD = '(';
+
+   static final char SIGC_END_CLASS = ';';
+
+   static final char SIGC_END_METHOD = ')';
+
+   static final char SIGC_PACKAGE = '/';
+
+   private static Logger logger = Logger.getLogger(Config.getLoggerName());
+
+   private ClassModel superClazz = null;
+
+   /**
+    * Create a ClassModel representing a given Class.
+    * 
+    * The class's classfile must be available from the class's classloader via <code>getClassLoader().getResourceAsStream(name))</code>. 
+    * For dynamic languages creating classes on the fly we may need another approach. 
+    * 
+    * @param _class The class we will extract the model from
+    * @throws ClassParseException
+    */
+
+   ClassModel(Class<?> _class) throws ClassParseException {
+
+      parse(_class);
+
+      Class<?> mySuper = _class.getSuperclass();
+      // Find better way to do this check
+      // The java.lang.Object test is for unit test framework to succeed - should 
+      // not occur in normal use
+      if ((mySuper != null) && (!mySuper.getName().equals(Kernel.class.getName()))
+            && (!mySuper.getName().equals("java.lang.Object"))) {
+         superClazz = new ClassModel(mySuper);
+      }
+   }
+
+   /**
+    * Determine if this is the superclass of some other named class.
+    * 
+    * @param otherClassName The name of the class to compare against
+    * @return true if 'this' a superclass of another named class 
+    */
+   boolean isSuperClass(String otherClassName) {
+      if (getClassWeAreModelling().getName().equals(otherClassName)) {
+         return true;
+      } else if (superClazz != null) {
+         return superClazz.isSuperClass(otherClassName);
+      } else {
+         return false;
+      }
+   }
+
+   /**
+    * Determine if this is the superclass of some other class.
+    * 
+    * @param otherClass The class to compare against
+    * @return true if 'this' a superclass of another class   
+    */
+   boolean isSuperClass(Class<?> other) {
+      Class<?> s = other.getSuperclass();
+      while (s != null) {
+         if (this.getClassWeAreModelling() == s || (this.getClassWeAreModelling().getName().equals(s.getName()))) {
+            return true;
+         }
+         s = s.getSuperclass();
+      }
+      return false;
+   }
+
+   /**
+    * Getter for superClazz
+    * 
+    * @return the superClazz ClassModel 
+    */
+   ClassModel getSuperClazz() {
+      return superClazz;
+   }
+
+   @Annotations.DocMe void replaceSuperClazz(ClassModel c) {
+      if (this.superClazz != null) {
+         assert c.isSuperClass(this.getClassWeAreModelling()) == true : "not my super";
+         if (this.superClazz.getClassWeAreModelling().getName().equals(c.getClassWeAreModelling().getName())) {
+            this.superClazz = c;
+         } else {
+            this.superClazz.replaceSuperClazz(c);
+         }
+      }
+   }
+
+   /**
+    * Convert a given JNI character type (say 'I') to its type name ('int').
+    * 
+    * @param _typeChar
+    * @return either a mapped type name or null if no mapping exists.
+    */
+   static String typeName(char _typeChar) {
+      String returnName = null;
+      switch (_typeChar) {
+         case SIGC_VOID:
+            returnName = "void";
+            break;
+         case SIGC_INT:
+            returnName = "int";
+            break;
+         case SIGC_DOUBLE:
+            returnName = "double";
+            break;
+         case SIGC_FLOAT:
+            returnName = "float";
+            break;
+         case SIGC_SHORT:
+            returnName = "short";
+            break;
+         case SIGC_CHAR:
+            returnName = "char";
+            break;
+         case SIGC_BYTE:
+            returnName = "byte";
+            break;
+         case SIGC_LONG:
+            returnName = "long";
+            break;
+         case SIGC_BOOLEAN:
+            returnName = "boolean";
+            break;
+      }
+      return (returnName);
+   }
+
+   static String convert(String _string) {
+      return (convert(_string, "", false));
+   }
+
+   static String convert(String _string, String _insert) {
+      return (convert(_string, _insert, false));
+   }
+
+   static String convert(String _string, String _insert, boolean _showFullClassName) {
+      Stack<String> stringStack = new Stack<String>();
+      Stack<String> methodStack = null;
+      int length = _string.length();
+      char[] chars = _string.toCharArray();
+      int i = 0;
+      boolean inArray = false;
+      boolean inMethod = false;
+      boolean inArgs = false;
+      int args = 0;
+      while (i < length) {
+         switch (chars[i]) {
+            case SIGC_CLASS: {
+               StringBuilder classNameBuffer = new StringBuilder();
+               i++;
+               while ((i < length) && chars[i] != SIGC_END_CLASS) {
+                  if (chars[i] == SIGC_PACKAGE) {
+                     classNameBuffer.append('.');
+                  } else {
+                     classNameBuffer.append(chars[i]);
+                  }
+                  i++;
+               }
+               i++; // step over SIGC_ENDCLASS
+               String className = classNameBuffer.toString();
+               if (_showFullClassName) {
+                  if (className.startsWith("java.lang")) {
+                     className = className.substring("java.lang.".length());
+                  }
+               } else {
+                  int lastDot = className.lastIndexOf('.');
+                  if (lastDot > 0) {
+                     className = className.substring(lastDot + 1);
+                  }
+               }
+               if (inArray) {
+                  // swap the stack items
+                  String popped = stringStack.pop();
+                  if (inArgs && args > 0) {
+                     stringStack.push(", ");
+                  }
+                  stringStack.push(className);
+                  stringStack.push(popped);
+                  inArray = false;
+               } else {
+                  if (inArgs && args > 0) {
+                     stringStack.push(", ");
+                  }
+                  stringStack.push(className);
+               }
+               args++;
+            }
+               break;
+            case SIGC_ARRAY: {
+               StringBuilder arrayDims = new StringBuilder();
+               while ((i < length) && chars[i] == SIGC_ARRAY) {
+                  arrayDims.append("[]");
+                  i++;
+               }
+               stringStack.push(arrayDims.toString());
+               inArray = true;
+            }
+               break;
+            case SIGC_VOID:
+            case SIGC_INT:
+            case SIGC_DOUBLE:
+            case SIGC_FLOAT:
+            case SIGC_SHORT:
+            case SIGC_CHAR:
+            case SIGC_BYTE:
+            case SIGC_LONG:
+            case SIGC_BOOLEAN: {
+               if (inArray) {
+                  // swap the stack items
+                  String popped = stringStack.pop();
+                  if (inArgs && args > 0) {
+                     stringStack.push(", ");
+                  }
+                  stringStack.push(typeName(chars[i]));
+                  stringStack.push(popped);
+                  inArray = false;
+               } else {
+                  if (inArgs && args > 0) {
+                     stringStack.push(", ");
+                  }
+                  stringStack.push(typeName(chars[i]));
+               }
+               i++; // step over this
+            }
+               break;
+            case SIGC_START_METHOD: {
+               stringStack.push("(");
+               i++; // step over this
+               inArgs = true;
+               args = 0;
+            }
+               break;
+            case SIGC_END_METHOD: {
+               inMethod = true;
+               inArgs = false;
+               stringStack.push(")");
+               methodStack = stringStack;
+               stringStack = new Stack<String>();
+               i++; // step over this
+            }
+               break;
+         }
+      }
+
+      StringBuilder returnValue = new StringBuilder();
+      for (String s : stringStack) {
+         returnValue.append(s);
+         returnValue.append(" ");
+
+      }
+      if (inMethod) {
+         for (String s : methodStack) {
+            returnValue.append(s);
+            returnValue.append(" ");
+         }
+      } else {
+         returnValue.append(_insert);
+      }
+      return (returnValue.toString());
+   }
+
+   static class MethodDescription{
+      private String className;
+
+      private String methodName;
+
+      private String type;
+
+      private String[] args;
+
+      MethodDescription(String _className, String _methodName, String _type, String[] _args) {
+         methodName = _methodName;
+         className = _className;
+         type = _type;
+         args = _args;
+      }
+
+      String[] getArgs() {
+         return (args);
+      }
+
+      String getType() {
+         return (type);
+      }
+
+      String getClassName() {
+         return (className);
+      }
+
+      String getMethodName() {
+         return (methodName);
+      }
+   }
+
+   static MethodDescription getMethodDescription(String _string) {
+      String className = null;
+      String methodName = null;
+      String descriptor = null;
+      MethodDescription methodDescription = null;
+      if (_string.startsWith("(")) {
+         className = "?";
+         methodName = "?";
+         descriptor = _string;
+      } else {
+         int parenIndex = _string.indexOf("(");
+         int dotIndex = _string.indexOf(".");
+         descriptor = _string.substring(parenIndex);
+         className = _string.substring(0, dotIndex);
+         methodName = _string.substring(dotIndex + 1, parenIndex);
+      }
+      Stack<String> stringStack = new Stack<String>();
+      Stack<String> methodStack = null;
+      int length = descriptor.length();
+      char[] chars = new char[descriptor.length()];
+      descriptor.getChars(0, descriptor.length(), chars, 0);
+      int i = 0;
+      boolean inArray = false;
+      boolean inMethod = false;
+      while (i < length) {
+         switch (chars[i]) {
+            case SIGC_CLASS: {
+               StringBuilder stringBuffer = null;
+               if (inArray) {
+                  stringBuffer = new StringBuilder(stringStack.pop());
+               } else {
+                  stringBuffer = new StringBuilder();
+               }
+               while ((i < length) && chars[i] != SIGC_END_CLASS) {
+                  stringBuffer.append(chars[i]);
+                  i++;
+               }
+               stringBuffer.append(chars[i]);
+               i++; // step over SIGC_ENDCLASS
+               stringStack.push(stringBuffer.toString());
+               inArray = false;
+            }
+               break;
+            case SIGC_ARRAY: {
+               StringBuilder stringBuffer = new StringBuilder();
+               while ((i < length) && chars[i] == SIGC_ARRAY) {
+                  stringBuffer.append(chars[i]);
+                  i++;
+               }
+               stringStack.push(stringBuffer.toString());
+               inArray = true;
+            }
+               break;
+            case SIGC_VOID:
+            case SIGC_INT:
+            case SIGC_DOUBLE:
+            case SIGC_FLOAT:
+            case SIGC_SHORT:
+            case SIGC_CHAR:
+            case SIGC_BYTE:
+            case SIGC_LONG:
+            case SIGC_BOOLEAN: {
+               StringBuilder stringBuffer = null;
+               if (inArray) {
+                  stringBuffer = new StringBuilder(stringStack.pop());
+               } else {
+                  stringBuffer = new StringBuilder();
+               }
+               stringBuffer.append(chars[i]);
+               i++; // step over this
+               stringStack.push(stringBuffer.toString());
+               inArray = false;
+            }
+               break;
+            case SIGC_START_METHOD: {
+               i++; // step over this
+            }
+               break;
+            case SIGC_END_METHOD: {
+               inMethod = true;
+               inArray = false;
+               methodStack = stringStack;
+               stringStack = new Stack<String>();
+               i++; // step over this
+            }
+               break;
+         }
+      }
+      if (inMethod) {
+         methodDescription = new MethodDescription(className, methodName, stringStack.toArray(new String[0])[0], methodStack
+               .toArray(new String[0]));
+      } else {
+         System.out.println("can't convert to a description");
+      }
+      return (methodDescription);
+   }
+
+   private int magic;
+
+   private int minorVersion;
+
+   private int majorVersion;
+
+   private ConstantPool constantPool;
+
+   private int accessFlags;
+
+   private int thisClassConstantPoolIndex;
+
+   private int superClassConstantPoolIndex;
+
+   private List<ClassModelInterface> interfaces = new ArrayList<ClassModelInterface>();
+
+   private List<ClassModelField> fields = new ArrayList<ClassModelField>();
+
+   private List<ClassModelMethod> methods = new ArrayList<ClassModelMethod>();
+
+   private AttributePool attributePool;
+
+   enum ConstantPoolType {
+      EMPTY,
+      UTF8,
+      UNICODE,
+      INTEGER,
+      FLOAT,
+      LONG,
+      DOUBLE,
+      CLASS,
+      STRING,
+      FIELD,
+      METHOD,
+      INTERFACEMETHOD,
+      NAMEANDTYPE
+   };
+
+   enum Access {
+      PUBLIC(0x00000001),
+      PRIVATE(0x00000002),
+      PROTECTED(0x00000004),
+      STATIC(0x00000008),
+      FINAL(0x00000010),
+      ACC_SYNCHRONIZED(0x00000020),
+      ACC_VOLATILE(0x00000040),
+      BRIDGE(0x00000040),
+      TRANSIENT(0x00000080),
+      VARARGS(0x00000080),
+      NATIVE(0x00000100),
+      INTERFACE(0x00000200),
+      ABSTRACT(0x00000400),
+      SUPER(0x00000020),
+      STRICT(0x00000800),
+      ANNOTATION(0x00002000),
+      ACC_ENUM(0x00004000);
+      int bits;
+
+      Access(int _bits) {
+         bits = _bits;
+      }
+
+      boolean bitIsSet(int _accessFlags) {
+         return ((bits & _accessFlags) == bits);
+      }
+
+      String convert(int _accessFlags) {
+         StringBuffer stringBuffer = new StringBuffer();
+         for (Access access : Access.values()) {
+            if (access.bitIsSet(_accessFlags)) {
+               stringBuffer.append(" " + access.name().toLowerCase());
+            }
+         }
+         return (stringBuffer.toString());
+      }
+   }
+
+   private static enum SignatureParseState {
+      skipping,
+      counting,
+      inclass,
+      inArray,
+      done;
+   };
+
+   class ConstantPool implements Iterable<ConstantPool.Entry>{
+
+      private List<Entry> entries = new ArrayList<Entry>();
+
+      abstract class Entry{
+         private ConstantPoolType constantPoolType;
+
+         private int slot;
+
+         Entry(ByteReader _byteReader, int _slot, ConstantPoolType _constantPoolType) {
+            constantPoolType = _constantPoolType;
+            slot = _slot;
+         }
+
+         ConstantPoolType getConstantPoolType() {
+            return (constantPoolType);
+         }
+
+         int getSlot() {
+            return (slot);
+         }
+
+      }
+
+      class ClassEntry extends Entry{
+
+         private int nameIndex;
+
+         ClassEntry(ByteReader _byteReader, int _slot) {
+            super(_byteReader, _slot, ConstantPoolType.CLASS);
+            nameIndex = _byteReader.u2();
+         }
+
+         int getNameIndex() {
+            return (nameIndex);
+         }
+
+         UTF8Entry getNameUTF8Entry() {
+            return (ConstantPool.this.getUTF8Entry(nameIndex));
+         }
+
+      }
+
+      class DoubleEntry extends Entry{
+         private double doubleValue;
+
+         DoubleEntry(ByteReader _byteReader, int _slot) {
+            super(_byteReader, _slot, ConstantPoolType.DOUBLE);
+            doubleValue = _byteReader.d8();
+         }
+
+         double getDoubleValue() {
+            return (doubleValue);
+         }
+
+      }
+
+      class EmptyEntry extends Entry{
+         EmptyEntry(ByteReader _byteReader, int _slot) {
+            super(_byteReader, _slot, ConstantPoolType.EMPTY);
+         }
+
+      }
+
+      class FieldEntry extends ReferenceEntry{
+
+         FieldEntry(ByteReader _byteReader, int _slot) {
+            super(_byteReader, _slot, ConstantPoolType.FIELD);
+         }
+
+      }
+
+      class FloatEntry extends Entry{
+         private float floatValue;
+
+         FloatEntry(ByteReader _byteReader, int _slot) {
+            super(_byteReader, _slot, ConstantPoolType.FLOAT);
+            floatValue = _byteReader.f4();
+         }
+
+         float getFloatValue() {
+            return (floatValue);
+         }
+
+      }
+
+      class IntegerEntry extends Entry{
+         private int intValue;
+
+         IntegerEntry(ByteReader _byteReader, int _slot) {
+            super(_byteReader, _slot, ConstantPoolType.INTEGER);
+            intValue = _byteReader.u4();
+         }
+
+         int getIntValue() {
+            return (intValue);
+         }
+
+      }
+
+      class InterfaceMethodEntry extends MethodReferenceEntry{
+         InterfaceMethodEntry(ByteReader _byteReader, int _slot) {
+            super(_byteReader, _slot, ConstantPoolType.INTERFACEMETHOD);
+         }
+      }
+
+      class LongEntry extends Entry{
+         private long longValue;
+
+         LongEntry(ByteReader _byteReader, int _slot) {
+            super(_byteReader, _slot, ConstantPoolType.LONG);
+            longValue = _byteReader.u8();
+         }
+
+         long getLongValue() {
+            return (longValue);
+         }
+
+      }
+
+      class MethodEntry extends MethodReferenceEntry{
+
+         MethodEntry(ByteReader _byteReader, int _slot) {
+            super(_byteReader, _slot, ConstantPoolType.METHOD);
+         }
+
+         @Override public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append(getClassEntry().getNameUTF8Entry().getUTF8());
+            sb.append(".");
+            sb.append(getNameAndTypeEntry().getNameUTF8Entry().getUTF8());
+            sb.append(getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8());
+            return (sb.toString());
+         }
+
+      }
+
+      class NameAndTypeEntry extends Entry{
+         private int descriptorIndex;
+
+         private int nameIndex;
+
+         NameAndTypeEntry(ByteReader _byteReader, int _slot) {
+            super(_byteReader, _slot, ConstantPoolType.NAMEANDTYPE);
+            nameIndex = _byteReader.u2();
+            descriptorIndex = _byteReader.u2();
+         }
+
+         int getDescriptorIndex() {
+            return (descriptorIndex);
+         }
+
+         UTF8Entry getDescriptorUTF8Entry() {
+            return (ConstantPool.this.getUTF8Entry(descriptorIndex));
+         }
+
+         int getNameIndex() {
+            return (nameIndex);
+         }
+
+         UTF8Entry getNameUTF8Entry() {
+            return (ConstantPool.this.getUTF8Entry(nameIndex));
+         }
+
+      }
+
+      abstract class MethodReferenceEntry extends ReferenceEntry{
+
+         class Arg extends Type{
+            Arg(String _signature, int _start, int _pos, int _argc) {
+               super(_signature.substring(_start, _pos + 1));
+               argc = _argc;
+            }
+
+            private int argc;
+
+            int getArgc() {
+               return (argc);
+            }
+         }
+
+         private Arg[] args = null;
+
+         private Type returnType = null;
+
+         @Override public int hashCode() {
+            NameAndTypeEntry nameAndTypeEntry = getNameAndTypeEntry();
+
+            return ((nameAndTypeEntry.getNameIndex() * 31 + nameAndTypeEntry.getDescriptorIndex()) * 31 + getClassIndex());
+         }
+
+         @Override public boolean equals(Object _other) {
+            if (_other == null || !(_other instanceof MethodReferenceEntry)) {
+               return (false);
+            } else {
+               MethodReferenceEntry otherMethodReferenceEntry = (MethodReferenceEntry) _other;
+               return (otherMethodReferenceEntry.getNameAndTypeEntry().getNameIndex() == getNameAndTypeEntry().getNameIndex()
+                     && otherMethodReferenceEntry.getNameAndTypeEntry().getDescriptorIndex() == getNameAndTypeEntry()
+                           .getDescriptorIndex() && otherMethodReferenceEntry.getClassIndex() == getClassIndex());
+            }
+         }
+
+         MethodReferenceEntry(ByteReader byteReader, int slot, ConstantPoolType constantPoolType) {
+            super(byteReader, slot, constantPoolType);
+
+         }
+
+         int getStackProduceCount() {
+            return (getReturnType().isVoid() ? 0 : 1);
+         }
+
+         Type getReturnType() {
+            if (returnType == null) {
+               getArgs();
+            }
+            return (returnType);
+         }
+
+         Arg[] getArgs() {
+            if (args == null || returnType == null) {
+               List<Arg> argList = new ArrayList<Arg>();
+               NameAndTypeEntry nameAndTypeEntry = getNameAndTypeEntry();
+
+               String signature = nameAndTypeEntry.getDescriptorUTF8Entry().getUTF8();// "([[IF)V" for a method that takes an int[][], float and returns void.
+               // Sadly we need to parse this, we need the # of arguments for the call
+               SignatureParseState state = SignatureParseState.skipping;
+               int start = 0;
+
+               for (int pos = 0; state != SignatureParseState.done; pos++) {
+                  char ch = signature.charAt(pos);
+                  switch (ch) {
+                     case '(':
+                        state = SignatureParseState.counting;
+                        break;
+                     case ')':
+                        state = SignatureParseState.done;
+                        returnType = new Type(signature.substring(pos + 1));
+                        break;
+                     case '[':
+                        switch (state) {
+                           case counting:
+                              state = SignatureParseState.inArray;
+                              start = pos;
+                              break;
+
+                        }
+                        // we don't care about arrays
+                        break;
+                     case 'L':
+                        // beginning of Ljava/lang/String; or something
+
+                        switch (state) {
+                           case counting:
+                              start = pos;
+                              // fallthrough intended!!
+                           case inArray:
+                              state = SignatureParseState.inclass;
+                              break;
+                        }
+                        break;
+                     case ';':
+                        // note we will only be in 'inclass' if we were previously counting, so this is safe
+                        switch (state) {
+                           case inclass:
+                              argList.add(new Arg(signature, start, pos, argList.size()));
+                              state = SignatureParseState.counting;
+                              break;
+                        }
+                        break;
+
+                     default:
+                        // we have IJBZDF so inc counter if we are still counting
+                        switch (state) {
+                           case counting:
+                              start = pos;
+                              // fallthrough intended!!
+                           case inArray:
+                              argList.add(new Arg(signature, start, pos, argList.size()));
+                              break;
+
+                        }
+                        break;
+                  }
+
+               }
+               // System.out.println("method "+name+" has signature of "+signature+" which has "+count+" args");
+
+               args = argList.toArray(new Arg[0]);
+            }
+            return (args);
+
+         }
+
+         int getStackConsumeCount() {
+            return (getArgs().length);
+         }
+      }
+
+      abstract class ReferenceEntry extends Entry{
+         protected int referenceClassIndex;
+
+         protected int nameAndTypeIndex;
+
+         protected int argCount = -1;
+
+         ReferenceEntry(ByteReader _byteReader, int _slot, ConstantPoolType _constantPoolType) {
+            super(_byteReader, _slot, _constantPoolType);
+            referenceClassIndex = _byteReader.u2();
+            nameAndTypeIndex = _byteReader.u2();
+         }
+
+         ClassEntry getClassEntry() {
+            return (ConstantPool.this.getClassEntry(referenceClassIndex));
+         }
+
+         int getClassIndex() {
+            return (referenceClassIndex);
+         }
+
+         NameAndTypeEntry getNameAndTypeEntry() {
+            return (ConstantPool.this.getNameAndTypeEntry(nameAndTypeIndex));
+         }
+
+         int getNameAndTypeIndex() {
+            return (nameAndTypeIndex);
+         }
+
+         boolean same(Entry _entry) {
+            if (_entry instanceof ReferenceEntry) {
+               ReferenceEntry entry = (ReferenceEntry) _entry;
+               return ((referenceClassIndex == entry.referenceClassIndex) && (nameAndTypeIndex == entry.nameAndTypeIndex));
+            }
+            return (false);
+         }
+
+         class Type{
+            private int arrayDimensions = 0;
+
+            Type(String _type) {
+               type = _type;
+
+               while (type.charAt(arrayDimensions) == '[') {
+                  arrayDimensions++;
+               }
+               type = type.substring(arrayDimensions);
+            }
+
+            String getType() {
+               return (type);
+            }
+
+            boolean isVoid() {
+               return (type.equals("V"));
+            }
+
+            private String type;
+
+            final boolean isArray() {
+               return (arrayDimensions > 0);
+            }
+
+            final int getArrayDimensions() {
+               return (arrayDimensions);
+            }
+
+         }
+
+      }
+
+      class StringEntry extends Entry{
+         private int utf8Index;
+
+         StringEntry(ByteReader _byteReader, int _slot) {
+            super(_byteReader, _slot, ConstantPoolType.STRING);
+            utf8Index = _byteReader.u2();
+         }
+
+         int getUTF8Index() {
+            return (utf8Index);
+         }
+
+         UTF8Entry getStringUTF8Entry() {
+            return (ConstantPool.this.getUTF8Entry(utf8Index));
+         }
+      }
+
+      class UTF8Entry extends Entry{
+         private String UTF8;
+
+         UTF8Entry(ByteReader _byteReader, int _slot) {
+            super(_byteReader, _slot, ConstantPoolType.UTF8);
+            UTF8 = _byteReader.utf8();
+         }
+
+         String getUTF8() {
+            return (UTF8);
+         }
+
+      }
+
+      ConstantPool(ByteReader _byteReader) {
+         int size = _byteReader.u2();
+         add(new EmptyEntry(_byteReader, 0)); // slot 0
+
+         for (int i = 1; i < size; i++) {
+            ConstantPoolType constantPoolType = ConstantPoolType.values()[_byteReader.u1()];
+
+            switch (constantPoolType) {
+               case UTF8:
+                  add(new UTF8Entry(_byteReader, i));
+                  break;
+               case INTEGER:
+                  add(new IntegerEntry(_byteReader, i));
+                  break;
+               case FLOAT:
+                  add(new FloatEntry(_byteReader, i));
+                  break;
+               case LONG:
+                  add(new LongEntry(_byteReader, i));
+                  i++;// Longs take two slots in the ConstantPool
+                  add(new EmptyEntry(_byteReader, i));
+                  break;
+               case DOUBLE:
+                  add(new DoubleEntry(_byteReader, i));
+                  i++; // Doubles take two slots in the ConstantPool
+                  add(new EmptyEntry(_byteReader, i));
+                  break;
+               case CLASS:
+                  add(new ClassEntry(_byteReader, i));
+                  break;
+               case STRING:
+                  add(new StringEntry(_byteReader, i));
+                  break;
+               case FIELD:
+                  add(new FieldEntry(_byteReader, i));
+                  break;
+               case METHOD:
+                  add(new MethodEntry(_byteReader, i));
+                  break;
+               case INTERFACEMETHOD:
+                  add(new InterfaceMethodEntry(_byteReader, i));
+                  break;
+               case NAMEANDTYPE:
+                  add(new NameAndTypeEntry(_byteReader, i));
+                  break;
+               default:
+                  System.out.printf("slot %04x unexpected Constant constantPoolType = %s\n", i, constantPoolType);
+
+            }
+
+         }
+      }
+
+      ClassEntry getClassEntry(int _index) {
+         try {
+            return ((ClassEntry) entries.get(_index));
+         } catch (ClassCastException e) {
+            return (null);
+         }
+      }
+
+      DoubleEntry getDoubleEntry(int _index) {
+         try {
+            return ((DoubleEntry) entries.get(_index));
+         } catch (ClassCastException e) {
+            return (null);
+         }
+      }
+
+      FieldEntry getFieldEntry(int _index) {
+         try {
+            return ((FieldEntry) entries.get(_index));
+         } catch (ClassCastException e) {
+            return (null);
+         }
+      }
+
+      FloatEntry getFloatEntry(int _index) {
+         try {
+            return ((FloatEntry) entries.get(_index));
+         } catch (ClassCastException e) {
+            return (null);
+         }
+      }
+
+      IntegerEntry getIntegerEntry(int _index) {
+         try {
+            return ((IntegerEntry) entries.get(_index));
+         } catch (ClassCastException e) {
+            return (null);
+         }
+      }
+
+      InterfaceMethodEntry getInterfaceMethodEntry(int _index) {
+         try {
+            return ((InterfaceMethodEntry) entries.get(_index));
+         } catch (ClassCastException e) {
+            return (null);
+         }
+      }
+
+      LongEntry getLongEntry(int _index) {
+         try {
+            return ((LongEntry) entries.get(_index));
+         } catch (ClassCastException e) {
+            return (null);
+         }
+      }
+
+      MethodEntry getMethodEntry(int _index) {
+         try {
+            return ((MethodEntry) entries.get(_index));
+         } catch (ClassCastException e) {
+            return (null);
+         }
+      }
+
+      NameAndTypeEntry getNameAndTypeEntry(int _index) {
+         try {
+            return ((NameAndTypeEntry) entries.get(_index));
+         } catch (ClassCastException e) {
+            return (null);
+         }
+      }
+
+      StringEntry getStringEntry(int _index) {
+         try {
+            return ((StringEntry) entries.get(_index));
+         } catch (ClassCastException e) {
+            return (null);
+         }
+      }
+
+      UTF8Entry getUTF8Entry(int _index) {
+         try {
+            return ((UTF8Entry) entries.get(_index));
+         } catch (ClassCastException e) {
+            return (null);
+         }
+      }
+
+      void add(Entry _entry) {
+         entries.add(_entry);
+
+      }
+
+      @Override public Iterator<Entry> iterator() {
+         return (entries.iterator());
+      }
+
+      Entry get(int _index) {
+         return (entries.get(_index));
+      }
+
+      String getDescription(ConstantPool.Entry _entry) {
+         StringBuilder sb = new StringBuilder();
+         if (_entry instanceof ConstantPool.EmptyEntry) {
+            ;
+         } else if (_entry instanceof ConstantPool.DoubleEntry) {
+            ConstantPool.DoubleEntry doubleEntry = (ConstantPool.DoubleEntry) _entry;
+            sb.append(doubleEntry.getDoubleValue());
+         } else if (_entry instanceof ConstantPool.FloatEntry) {
+            ConstantPool.FloatEntry floatEntry = (ConstantPool.FloatEntry) _entry;
+            sb.append(floatEntry.getFloatValue());
+         } else if (_entry instanceof ConstantPool.IntegerEntry) {
+            ConstantPool.IntegerEntry integerEntry = (ConstantPool.IntegerEntry) _entry;
+            sb.append(integerEntry.getIntValue());
+         } else if (_entry instanceof ConstantPool.LongEntry) {
+            ConstantPool.LongEntry longEntry = (ConstantPool.LongEntry) _entry;
+            sb.append(longEntry.getLongValue());
+         } else if (_entry instanceof ConstantPool.UTF8Entry) {
+            ConstantPool.UTF8Entry utf8Entry = (ConstantPool.UTF8Entry) _entry;
+            sb.append(utf8Entry.getUTF8());
+         } else if (_entry instanceof ConstantPool.StringEntry) {
+            ConstantPool.StringEntry stringEntry = (ConstantPool.StringEntry) _entry;
+            ConstantPool.UTF8Entry utf8Entry = (ConstantPool.UTF8Entry) get(stringEntry.getUTF8Index());
+            sb.append(utf8Entry.getUTF8());
+         } else if (_entry instanceof ConstantPool.ClassEntry) {
+            ConstantPool.ClassEntry classEntry = (ConstantPool.ClassEntry) _entry;
+            ConstantPool.UTF8Entry utf8Entry = (ConstantPool.UTF8Entry) get(classEntry.getNameIndex());
+            sb.append(utf8Entry.getUTF8());
+         } else if (_entry instanceof ConstantPool.NameAndTypeEntry) {
+            ConstantPool.NameAndTypeEntry nameAndTypeEntry = (ConstantPool.NameAndTypeEntry) _entry;
+            ConstantPool.UTF8Entry utf8NameEntry = (ConstantPool.UTF8Entry) get(nameAndTypeEntry.getNameIndex());
+            ConstantPool.UTF8Entry utf8DescriptorEntry = (ConstantPool.UTF8Entry) get(nameAndTypeEntry.getDescriptorIndex());
+            sb.append(utf8NameEntry.getUTF8() + "." + utf8DescriptorEntry.getUTF8());
+         } else if (_entry instanceof ConstantPool.MethodEntry) {
+            ConstantPool.MethodEntry methodEntry = (ConstantPool.MethodEntry) _entry;
+            ConstantPool.ClassEntry classEntry = (ConstantPool.ClassEntry) get(methodEntry.getClassIndex());
+            ConstantPool.UTF8Entry utf8Entry = (ConstantPool.UTF8Entry) get(classEntry.getNameIndex());
+            ConstantPool.NameAndTypeEntry nameAndTypeEntry = (ConstantPool.NameAndTypeEntry) get(methodEntry.getNameAndTypeIndex());
+            ConstantPool.UTF8Entry utf8NameEntry = (ConstantPool.UTF8Entry) get(nameAndTypeEntry.getNameIndex());
+            ConstantPool.UTF8Entry utf8DescriptorEntry = (ConstantPool.UTF8Entry) get(nameAndTypeEntry.getDescriptorIndex());
+            sb.append(convert(utf8DescriptorEntry.getUTF8(), utf8Entry.getUTF8() + "." + utf8NameEntry.getUTF8()));
+         } else if (_entry instanceof ConstantPool.InterfaceMethodEntry) {
+            ConstantPool.InterfaceMethodEntry interfaceMethodEntry = (ConstantPool.InterfaceMethodEntry) _entry;
+            ConstantPool.ClassEntry classEntry = (ConstantPool.ClassEntry) get(interfaceMethodEntry.getClassIndex());
+            ConstantPool.UTF8Entry utf8Entry = (ConstantPool.UTF8Entry) get(classEntry.getNameIndex());
+            ConstantPool.NameAndTypeEntry nameAndTypeEntry = (ConstantPool.NameAndTypeEntry) get(interfaceMethodEntry
+                  .getNameAndTypeIndex());
+            ConstantPool.UTF8Entry utf8NameEntry = (ConstantPool.UTF8Entry) get(nameAndTypeEntry.getNameIndex());
+            ConstantPool.UTF8Entry utf8DescriptorEntry = (ConstantPool.UTF8Entry) get(nameAndTypeEntry.getDescriptorIndex());
+            sb.append(convert(utf8DescriptorEntry.getUTF8(), utf8Entry.getUTF8() + "." + utf8NameEntry.getUTF8()));
+         } else if (_entry instanceof ConstantPool.FieldEntry) {
+            ConstantPool.FieldEntry fieldEntry = (ConstantPool.FieldEntry) _entry;
+            ConstantPool.ClassEntry classEntry = (ConstantPool.ClassEntry) get(fieldEntry.getClassIndex());
+            ConstantPool.UTF8Entry utf8Entry = (ConstantPool.UTF8Entry) get(classEntry.getNameIndex());
+            ConstantPool.NameAndTypeEntry nameAndTypeEntry = (ConstantPool.NameAndTypeEntry) get(fieldEntry.getNameAndTypeIndex());
+            ConstantPool.UTF8Entry utf8NameEntry = (ConstantPool.UTF8Entry) get(nameAndTypeEntry.getNameIndex());
+            ConstantPool.UTF8Entry utf8DescriptorEntry = (ConstantPool.UTF8Entry) get(nameAndTypeEntry.getDescriptorIndex());
+            sb.append(convert(utf8DescriptorEntry.getUTF8(), utf8Entry.getUTF8() + "." + utf8NameEntry.getUTF8()));
+         }
+         return (sb.toString());
+      }
+
+      int[] getConstantPoolReferences(ConstantPool.Entry _entry) {
+         int[] references = new int[0];
+         if (_entry instanceof ConstantPool.StringEntry) {
+            ConstantPool.StringEntry stringEntry = (ConstantPool.StringEntry) _entry;
+            references = new int[] {
+               stringEntry.getUTF8Index()
+            };
+         } else if (_entry instanceof ConstantPool.ClassEntry) {
+            ConstantPool.ClassEntry classEntry = (ConstantPool.ClassEntry) _entry;
+            references = new int[] {
+               classEntry.getNameIndex()
+            };
+         } else if (_entry instanceof ConstantPool.NameAndTypeEntry) {
+            ConstantPool.NameAndTypeEntry nameAndTypeEntry = (ConstantPool.NameAndTypeEntry) _entry;
+            references = new int[] {
+                  nameAndTypeEntry.getNameIndex(),
+                  nameAndTypeEntry.getDescriptorIndex()
+            };
+         } else if (_entry instanceof ConstantPool.MethodEntry) {
+            ConstantPool.MethodEntry methodEntry = (ConstantPool.MethodEntry) _entry;
+            ConstantPool.ClassEntry classEntry = (ConstantPool.ClassEntry) get(methodEntry.getClassIndex());
+            @SuppressWarnings("unused") ConstantPool.UTF8Entry utf8Entry = (ConstantPool.UTF8Entry) get(classEntry.getNameIndex());
+            ConstantPool.NameAndTypeEntry nameAndTypeEntry = (ConstantPool.NameAndTypeEntry) get(methodEntry.getNameAndTypeIndex());
+            @SuppressWarnings("unused") ConstantPool.UTF8Entry utf8NameEntry = (ConstantPool.UTF8Entry) get(nameAndTypeEntry
+                  .getNameIndex());
+            @SuppressWarnings("unused") ConstantPool.UTF8Entry utf8DescriptorEntry = (ConstantPool.UTF8Entry) get(nameAndTypeEntry
+                  .getDescriptorIndex());
+            references = new int[] {
+                  methodEntry.getClassIndex(),
+                  classEntry.getNameIndex(),
+                  nameAndTypeEntry.getNameIndex(),
+                  nameAndTypeEntry.getDescriptorIndex()
+            };
+         } else if (_entry instanceof ConstantPool.InterfaceMethodEntry) {
+            ConstantPool.InterfaceMethodEntry interfaceMethodEntry = (ConstantPool.InterfaceMethodEntry) _entry;
+            ConstantPool.ClassEntry classEntry = (ConstantPool.ClassEntry) get(interfaceMethodEntry.getClassIndex());
+            @SuppressWarnings("unused") ConstantPool.UTF8Entry utf8Entry = (ConstantPool.UTF8Entry) get(classEntry.getNameIndex());
+            ConstantPool.NameAndTypeEntry nameAndTypeEntry = (ConstantPool.NameAndTypeEntry) get(interfaceMethodEntry
+                  .getNameAndTypeIndex());
+            @SuppressWarnings("unused") ConstantPool.UTF8Entry utf8NameEntry = (ConstantPool.UTF8Entry) get(nameAndTypeEntry
+                  .getNameIndex());
+            @SuppressWarnings("unused") ConstantPool.UTF8Entry utf8DescriptorEntry = (ConstantPool.UTF8Entry) get(nameAndTypeEntry
+                  .getDescriptorIndex());
+            references = new int[] {
+                  interfaceMethodEntry.getClassIndex(),
+                  classEntry.getNameIndex(),
+                  nameAndTypeEntry.getNameIndex(),
+                  nameAndTypeEntry.getDescriptorIndex()
+            };
+         } else if (_entry instanceof ConstantPool.FieldEntry) {
+            ConstantPool.FieldEntry fieldEntry = (ConstantPool.FieldEntry) _entry;
+            ConstantPool.ClassEntry classEntry = (ConstantPool.ClassEntry) get(fieldEntry.getClassIndex());
+            @SuppressWarnings("unused") ConstantPool.UTF8Entry utf8Entry = (ConstantPool.UTF8Entry) get(classEntry.getNameIndex());
+            ConstantPool.NameAndTypeEntry nameAndTypeEntry = (ConstantPool.NameAndTypeEntry) get(fieldEntry.getNameAndTypeIndex());
+            @SuppressWarnings("unused") ConstantPool.UTF8Entry utf8NameEntry = (ConstantPool.UTF8Entry) get(nameAndTypeEntry
+                  .getNameIndex());
+            @SuppressWarnings("unused") ConstantPool.UTF8Entry utf8DescriptorEntry = (ConstantPool.UTF8Entry) get(nameAndTypeEntry
+                  .getDescriptorIndex());
+            references = new int[] {
+                  fieldEntry.getClassIndex(),
+                  classEntry.getNameIndex(),
+                  nameAndTypeEntry.getNameIndex(),
+                  nameAndTypeEntry.getDescriptorIndex()
+            };
+         }
+         return (references);
+      }
+
+      String getType(ConstantPool.Entry _entry) {
+         StringBuffer sb = new StringBuffer();
+         if (_entry instanceof ConstantPool.EmptyEntry) {
+            sb.append("empty");
+         } else if (_entry instanceof ConstantPool.DoubleEntry) {
+            sb.append("double");
+         } else if (_entry instanceof ConstantPool.FloatEntry) {
+            sb.append("float");
+         } else if (_entry instanceof ConstantPool.IntegerEntry) {
+            sb.append("int");
+         } else if (_entry instanceof ConstantPool.LongEntry) {
+            sb.append("long");
+         } else if (_entry instanceof ConstantPool.UTF8Entry) {
+            sb.append("utf8");
+         } else if (_entry instanceof ConstantPool.StringEntry) {
+            sb.append("string");
+         } else if (_entry instanceof ConstantPool.ClassEntry) {
+            sb.append("class");
+         } else if (_entry instanceof ConstantPool.NameAndTypeEntry) {
+            sb.append("name/type");
+         } else if (_entry instanceof ConstantPool.MethodEntry) {
+            sb.append("method");
+         } else if (_entry instanceof ConstantPool.InterfaceMethodEntry) {
+            sb.append("interface method");
+         } else if (_entry instanceof ConstantPool.FieldEntry) {
+            sb.append("field");
+         }
+         return (sb.toString());
+      }
+
+      Object getConstantEntry(int _constantPoolIndex) {
+         Entry entry = get(_constantPoolIndex);
+         Object object = null;
+         switch (entry.getConstantPoolType()) {
+            case FLOAT:
+               object = ((FloatEntry) entry).getFloatValue();
+               break;
+            case DOUBLE:
+               object = ((DoubleEntry) entry).getDoubleValue();
+               break;
+            case INTEGER:
+               object = ((IntegerEntry) entry).getIntValue();
+               break;
+            case LONG:
+               object = ((LongEntry) entry).getLongValue();
+               break;
+            case STRING:
+               object = ((StringEntry) entry).getStringUTF8Entry().getUTF8();
+               break;
+         }
+         return (object);
+      }
+   }
+
+   class AttributePool{
+      private List<AttributePoolEntry> attributePoolEntries = new ArrayList<AttributePoolEntry>();
+
+      class CodeEntry extends AttributePoolEntry{
+
+         class ExceptionPoolEntry{
+            private int exceptionClassIndex;
+
+            private int end;
+
+            private int handler;
+
+            private int start;
+
+            ExceptionPoolEntry(ByteReader _byteReader) {
+               start = _byteReader.u2();
+               end = _byteReader.u2();
+               handler = _byteReader.u2();
+               exceptionClassIndex = _byteReader.u2();
+            }
+
+            ConstantPool.ClassEntry getClassEntry() {
+               return (constantPool.getClassEntry(exceptionClassIndex));
+            }
+
+            int getClassIndex() {
+               return (exceptionClassIndex);
+            }
+
+            int getEnd() {
+               return (end);
+            }
+
+            int getHandler() {
+               return (handler);
+            }
+
+            int getStart() {
+               return (start);
+            }
+
+         }
+
+         private List<ExceptionPoolEntry> exceptionPoolEntries = new ArrayList<ExceptionPoolEntry>();
+
+         private AttributePool codeEntryAttributePool;
+
+         private byte[] code;
+
+         private int maxLocals;
+
+         private int maxStack;
+
+         CodeEntry(ByteReader _byteReader, int _nameIndex, int _length) {
+            super(_byteReader, _nameIndex, _length);
+            maxStack = _byteReader.u2();
+            maxLocals = _byteReader.u2();
+            int codeLength = _byteReader.u4();
+            code = _byteReader.bytes(codeLength);
+            int exceptionTableLength = _byteReader.u2();
+            for (int i = 0; i < exceptionTableLength; i++) {
+               exceptionPoolEntries.add(new ExceptionPoolEntry(_byteReader));
+            }
+            codeEntryAttributePool = new AttributePool(_byteReader);
+         }
+
+         @Override AttributePool getAttributePool() {
+            return (codeEntryAttributePool);
+         }
+
+         LineNumberTableEntry getLineNumberTableEntry() {
+            return (codeEntryAttributePool.getLineNumberTableEntry());
+         }
+
+         int getMaxLocals() {
+            return (maxLocals);
+         }
+
+         int getMaxStack() {
+            return (maxStack);
+         }
+
+         byte[] getCode() {
+            return code;
+         }
+
+         List<ExceptionPoolEntry> getExceptionPoolEntries() {
+            return exceptionPoolEntries;
+         }
+      }
+
+      class ConstantValueEntry extends AttributePoolEntry{
+         private int index;
+
+         ConstantValueEntry(ByteReader _byteReader, int _nameIndex, int _length) {
+            super(_byteReader, _nameIndex, _length);
+            index = _byteReader.u2();
+         }
+
+         int getIndex() {
+            return (index);
+         }
+
+      }
+
+      class DeprecatedEntry extends AttributePoolEntry{
+         DeprecatedEntry(ByteReader _byteReader, int _nameIndex, int _length) {
+            super(_byteReader, _nameIndex, _length);
+         }
+
+      }
+
+      abstract class AttributePoolEntry{
+         protected int length;
+
+         protected int nameIndex;
+
+         AttributePoolEntry(ByteReader _byteReader, int _nameIndex, int _length) {
+            nameIndex = _nameIndex;
+            length = _length;
+         }
+
+         AttributePool getAttributePool() {
+            return (null);
+         }
+
+         int getLength() {
+            return (length);
+         }
+
+         String getName() {
+            return (constantPool.getUTF8Entry(nameIndex).getUTF8());
+         }
+
+         int getNameIndex() {
+            return (nameIndex);
+         }
+
+      }
+
+      abstract class PoolEntry<T> extends AttributePoolEntry implements Iterable<T>{
+         private List<T> pool = new ArrayList<T>();
+
+         List<T> getPool() {
+            return (pool);
+         }
+
+         PoolEntry(ByteReader _byteReader, int _nameIndex, int _length) {
+            super(_byteReader, _nameIndex, _length);
+         }
+
+         @Override public Iterator<T> iterator() {
+            return (pool.iterator());
+         }
+
+      }
+
+      class ExceptionEntry extends PoolEntry<Integer>{
+
+         ExceptionEntry(ByteReader _byteReader, int _nameIndex, int _length) {
+            super(_byteReader, _nameIndex, _length);
+            int exceptionTableLength = _byteReader.u2();
+            for (int i = 0; i < exceptionTableLength; i++) {
+               getPool().add(_byteReader.u2());
+            }
+         }
+
+      }
+
+      class InnerClassesEntry extends PoolEntry<InnerClassesEntry.InnerClassInfo>{
+         class InnerClassInfo{
+            private int innerAccess;
+
+            private int innerIndex;
+
+            private int innerNameIndex;
+
+            private int outerIndex;
+
+            InnerClassInfo(ByteReader _byteReader) {
+               innerIndex = _byteReader.u2();
+               outerIndex = _byteReader.u2();
+               innerNameIndex = _byteReader.u2();
+               innerAccess = _byteReader.u2();
+            }
+
+            int getInnerAccess() {
+               return (innerAccess);
+            }
+
+            int getInnerIndex() {
+               return (innerIndex);
+            }
+
+            int getInnerNameIndex() {
+               return (innerNameIndex);
+            }
+
+            int getOuterIndex() {
+               return (outerIndex);
+            }
+
+         }
+
+         InnerClassesEntry(ByteReader _byteReader, int _nameIndex, int _length) {
+            super(_byteReader, _nameIndex, _length);
+            int innerClassesTableLength = _byteReader.u2();
+            for (int i = 0; i < innerClassesTableLength; i++) {
+               getPool().add(new InnerClassInfo(_byteReader));
+            }
+         }
+
+      }
+
+      class LineNumberTableEntry extends PoolEntry<LineNumberTableEntry.StartLineNumberPair>{
+
+         class StartLineNumberPair{
+            private int lineNumber;
+
+            private int start;
+
+            StartLineNumberPair(ByteReader _byteReader) {
+               start = _byteReader.u2();
+               lineNumber = _byteReader.u2();
+            }
+
+            int getLineNumber() {
+               return (lineNumber);
+            }
+
+            int getStart() {
+               return (start);
+            }
+
+         }
+
+         LineNumberTableEntry(ByteReader _byteReader, int _nameIndex, int _length) {
+            super(_byteReader, _nameIndex, _length);
+            int lineNumberTableLength = _byteReader.u2();
+            for (int i = 0; i < lineNumberTableLength; i++) {
+               getPool().add(new StartLineNumberPair(_byteReader));
+            }
+         }
+
+         int getSourceLineNumber(int _start, boolean _exact) {
+            Iterator<StartLineNumberPair> i = getPool().iterator();
+            if (i.hasNext()) {
+               StartLineNumberPair from = i.next();
+               while (i.hasNext()) {
+                  StartLineNumberPair to = i.next();
+                  if (_exact) {
+                     if (_start == from.getStart()) {
+                        return (from.getLineNumber());
+                     }
+                  } else if (_start >= from.getStart() && _start < to.getStart()) {
+                     return (from.getLineNumber());
+                  }
+                  from = to;
+               }
+               if (_exact) {
+                  if (_start == from.getStart()) {
+                     return (from.getLineNumber());
+                  }
+               } else if (_start >= from.getStart()) {
+                  return (from.getLineNumber());
+               }
+            }
+            return (-1);
+         }
+
+      }
+
+      class EnclosingMethodEntry extends AttributePoolEntry{
+
+         EnclosingMethodEntry(ByteReader _byteReader, int _nameIndex, int _length) {
+            super(_byteReader, _nameIndex, _length);
+            enclosingClassIndex = _byteReader.u2();
+            enclosingMethodIndex = _byteReader.u2();
+         }
+
+         private int enclosingClassIndex;
+
+         int getClassIndex() {
+            return (enclosingClassIndex);
+         }
+
+         private int enclosingMethodIndex;
+
+         int getMethodIndex() {
+            return (enclosingMethodIndex);
+         }
+
+      }
+
+      class SignatureEntry extends AttributePoolEntry{
+
+         SignatureEntry(ByteReader _byteReader, int _nameIndex, int _length) {
+            super(_byteReader, _nameIndex, _length);
+            signatureIndex = _byteReader.u2();
+         }
+
+         private int signatureIndex;
+
+         int getSignatureIndex() {
+            return (signatureIndex);
+         }
+
+      }
+
+      class LocalVariableTableEntry extends PoolEntry<LocalVariableTableEntry.LocalVariableInfo>{
+
+         class LocalVariableInfo{
+            private int descriptorIndex;
+
+            private int usageLength;
+
+            private int variableNameIndex;
+
+            private int start;
+
+            private int variableIndex;
+
+            LocalVariableInfo(ByteReader _byteReader) {
+               start = _byteReader.u2();
+               usageLength = _byteReader.u2();
+               variableNameIndex = _byteReader.u2();
+               descriptorIndex = _byteReader.u2();
+               variableIndex = _byteReader.u2();
+            }
+
+            int getDescriptorIndex() {
+               return (descriptorIndex);
+            }
+
+            int getLength() {
+               return (usageLength);
+            }
+
+            int getNameIndex() {
+               return (variableNameIndex);
+            }
+
+            int getStart() {
+               return (start);
+            }
+
+            int getVariableIndex() {
+               return (variableIndex);
+            }
+
+            String getVariableName() {
+               return (constantPool.getUTF8Entry(variableNameIndex).getUTF8());
+            }
+
+            String getVariableDescriptor() {
+               return (constantPool.getUTF8Entry(descriptorIndex).getUTF8());
+            }
+
+            int getEnd() {
+               return (start + usageLength);
+            }
+         }
+
+         LocalVariableTableEntry(ByteReader _byteReader, int _nameIndex, int _length) {
+            super(_byteReader, _nameIndex, _length);
+            int localVariableTableLength = _byteReader.u2();
+            for (int i = 0; i < localVariableTableLength; i++) {
+               getPool().add(new LocalVariableInfo(_byteReader));
+            }
+         }
+
+         LocalVariableInfo getVariable(int _pc, int _index) {
+            LocalVariableInfo returnValue = null;
+            // System.out.println("pc = " + _pc + " index = " + _index);
+            for (LocalVariableInfo localVariableInfo : getPool()) {
+               // System.out.println("   start=" + localVariableInfo.getStart() + " length=" + localVariableInfo.getLength()
+               // + " varidx=" + localVariableInfo.getVariableIndex());
+               if (_pc >= localVariableInfo.getStart() - 1 && _pc <= (localVariableInfo.getStart() + localVariableInfo.getLength())
+                     && _index == localVariableInfo.getVariableIndex()) {
+                  returnValue = localVariableInfo;
+                  break;
+               }
+            }
+            // System.out.println("returning " + returnValue);
+            return (returnValue);
+         }
+
+         String getVariableName(int _pc, int _index) {
+            String returnValue = "unknown";
+            LocalVariableInfo localVariableInfo = getVariable(_pc, _index);
+            if (localVariableInfo != null) {
+               returnValue = convert(constantPool.getUTF8Entry(localVariableInfo.getDescriptorIndex()).getUTF8(), constantPool
+                     .getUTF8Entry(localVariableInfo.getNameIndex()).getUTF8());
+            }
+            // System.out.println("returning " + returnValue);
+            return (returnValue);
+         }
+
+      }
+
+      class OtherEntry extends AttributePoolEntry{
+         private byte[] bytes;
+
+         OtherEntry(ByteReader _byteReader, int _nameIndex, int _length) {
+            super(_byteReader, _nameIndex, _length);
+            bytes = _byteReader.bytes(_length);
+         }
+
+         byte[] getBytes() {
+            return (bytes);
+         }
+
+         @Override public String toString() {
+            return (new String(bytes));
+         }
+
+      }
+
+      class SourceFileEntry extends AttributePoolEntry{
+         private int sourceFileIndex;
+
+         SourceFileEntry(ByteReader _byteReader, int _nameIndex, int _length) {
+            super(_byteReader, _nameIndex, _length);
+            sourceFileIndex = _byteReader.u2();
+         }
+
+         int getSourceFileIndex() {
+            return (sourceFileIndex);
+         }
+
+         String getSourceFileName() {
+            return (constantPool.getUTF8Entry(sourceFileIndex).getUTF8());
+         }
+
+      }
+
+      class SyntheticEntry extends AttributePoolEntry{
+         SyntheticEntry(ByteReader _byteReader, int _nameIndex, int _length) {
+            super(_byteReader, _nameIndex, _length);
+         }
+
+      }
+
+      class RuntimeAnnotationsEntry extends PoolEntry<RuntimeAnnotationsEntry.AnnotationInfo>{
+
+         class AnnotationInfo{
+            private int typeIndex;
+
+            private int elementValuePairCount;
+
+            class ElementValuePair{
+               class Value{
+                  Value(int _tag) {
+                     tag = _tag;
+                  }
+
+                  int tag;
+
+               }
+
+               class PrimitiveValue extends Value{
+                  private int typeNameIndex;
+
+                  private int constNameIndex;
+
+                  PrimitiveValue(int _tag, ByteReader _byteReader) {
+                     super(_tag);
+                     typeNameIndex = _byteReader.u2();
+                     constNameIndex = _byteReader.u2();
+                  }
+
+                  int getConstNameIndex() {
+                     return (constNameIndex);
+                  }
+
+                  int getTypeNameIndex() {
+                     return (typeNameIndex);
+                  }
+               }
+
+               class EnumValue extends Value{
+                  EnumValue(int _tag, ByteReader _byteReader) {
+                     super(_tag);
+                  }
+
+               }
+
+               class ArrayValue extends Value{
+                  ArrayValue(int _tag, ByteReader _byteReader) {
+                     super(_tag);
+                  }
+
+               }
+
+               class ClassValue extends Value{
+                  ClassValue(int _tag, ByteReader _byteReader) {
+                     super(_tag);
+                  }
+
+               }
+
+               class AnnotationValue extends Value{
+                  AnnotationValue(int _tag, ByteReader _byteReader) {
+                     super(_tag);
+                  }
+
+               }
+
+               @SuppressWarnings("unused") private int elementNameIndex;
+
+               @SuppressWarnings("unused") private Value value;
+
+               ElementValuePair(ByteReader _byteReader) {
+                  elementNameIndex = _byteReader.u2();
+                  int tag = _byteReader.u1();
+
+                  switch (tag) {
+                     case SIGC_BYTE:
+                     case SIGC_CHAR:
+                     case SIGC_INT:
+                     case SIGC_LONG:
+                     case SIGC_DOUBLE:
+                     case SIGC_FLOAT:
+                     case SIGC_SHORT:
+                     case SIGC_BOOLEAN:
+                     case 's': // special for String
+                        value = new PrimitiveValue(tag, _byteReader);
+                        break;
+                     case 'e': // special for Enum
+                        value = new EnumValue(tag, _byteReader);
+                        break;
+                     case 'c': // special for class
+                        value = new ClassValue(tag, _byteReader);
+                        break;
+                     case '@': // special for Annotation
+                        value = new AnnotationValue(tag, _byteReader);
+                        break;
+                     case 'a': // special for array
+                        value = new ArrayValue(tag, _byteReader);
+                        break;
+                  }
+
+               }
+
+            }
+
+            ElementValuePair[] elementValuePairs;
+
+            AnnotationInfo(ByteReader _byteReader) {
+               typeIndex = _byteReader.u2();
+               elementValuePairCount = _byteReader.u2();
+               elementValuePairs = new ElementValuePair[elementValuePairCount];
+               for (int i = 0; i < elementValuePairCount; i++) {
+                  elementValuePairs[i] = new ElementValuePair(_byteReader);
+               }
+            }
+
+            int getTypeIndex() {
+               return (typeIndex);
+            }
+
+            String getTypeDescriptor() {
+               return (constantPool.getUTF8Entry(typeIndex).getUTF8());
+            }
+         }
+
+         RuntimeAnnotationsEntry(ByteReader _byteReader, int _nameIndex, int _length) {
+            super(_byteReader, _nameIndex, _length);
+            int localVariableTableLength = _byteReader.u2();
+            for (int i = 0; i < localVariableTableLength; i++) {
+               getPool().add(new AnnotationInfo(_byteReader));
+            }
+         }
+
+      }
+
+      private CodeEntry codeEntry = null;
+
+      private EnclosingMethodEntry enclosingMethodEntry = null;
+
+      private DeprecatedEntry deprecatedEntry = null;
+
+      private ExceptionEntry exceptionEntry = null;
+
+      private LineNumberTableEntry lineNumberTableEntry = null;
+
+      private LocalVariableTableEntry localVariableTableEntry = null;
+
+      private RuntimeAnnotationsEntry runtimeVisibleAnnotationsEntry;
+
+      private RuntimeAnnotationsEntry runtimeInvisibleAnnotationsEntry;
+
+      private SourceFileEntry sourceFileEntry = null;
+
+      private SyntheticEntry syntheticEntry = null;
+
+      private final static String LOCALVARIABLETABLE_TAG = "LocalVariableTable";
+
+      private final static String CONSTANTVALUE_TAG = "ConstantValue";
+
+      private final static String LINENUMBERTABLE_TAG = "LineNumberTable";
+
+      AttributePool(ByteReader _byteReader) {
+
+         int attributeCount = _byteReader.u2();
+         AttributePoolEntry entry = null;
+         for (int i = 0; i < attributeCount; i++) {
+            int attributeNameIndex = _byteReader.u2();
+            int length = _byteReader.u4();
+            String attributeName = constantPool.getUTF8Entry(attributeNameIndex).getUTF8();
+            if (attributeName.equals(LOCALVARIABLETABLE_TAG)) {
+               localVariableTableEntry = new LocalVariableTableEntry(_byteReader, attributeNameIndex, length);
+               entry = localVariableTableEntry;
+            } else if (attributeName.equals(CONSTANTVALUE_TAG)) {
+               entry = new ConstantValueEntry(_byteReader, attributeNameIndex, length);
+            } else if (attributeName.equals(LINENUMBERTABLE_TAG)) {
+               lineNumberTableEntry = new LineNumberTableEntry(_byteReader, attributeNameIndex, length);
+               entry = lineNumberTableEntry;
+            } else if (attributeName.equals("SourceFile")) {
+               sourceFileEntry = new SourceFileEntry(_byteReader, attributeNameIndex, length);
+               entry = sourceFileEntry;
+            } else if (attributeName.equals("Synthetic")) {
+               syntheticEntry = new SyntheticEntry(_byteReader, attributeNameIndex, length);
+               entry = syntheticEntry;
+            } else if (attributeName.equals("Exceptions")) {
+               exceptionEntry = new ExceptionEntry(_byteReader, attributeNameIndex, length);
+               entry = exceptionEntry;
+            } else if (attributeName.equals("InnerClasses")) {
+               entry = new InnerClassesEntry(_byteReader, attributeNameIndex, length);
+            } else if (attributeName.equals("Deprecated")) {
+               deprecatedEntry = new DeprecatedEntry(_byteReader, attributeNameIndex, length);
+               entry = deprecatedEntry;
+            } else if (attributeName.equals("Code")) {
+               codeEntry = new CodeEntry(_byteReader, attributeNameIndex, length);
+               entry = codeEntry;
+            } else if (attributeName.equals("EnclosingMethod")) {
+               enclosingMethodEntry = new EnclosingMethodEntry(_byteReader, attributeNameIndex, length);
+               entry = enclosingMethodEntry;
+            } else if (attributeName.equals("Signature")) {
+               entry = new SignatureEntry(_byteReader, attributeNameIndex, length);
+            } else if (attributeName.equals("RuntimeInvisibleAnnotations")) {
+               runtimeInvisibleAnnotationsEntry = new RuntimeAnnotationsEntry(_byteReader, attributeNameIndex, length);
+               entry = runtimeInvisibleAnnotationsEntry;
+            } else if (attributeName.equals("RuntimeVisibleAnnotations")) {
+               runtimeVisibleAnnotationsEntry = new RuntimeAnnotationsEntry(_byteReader, attributeNameIndex, length);
+               entry = runtimeVisibleAnnotationsEntry;
+            } else {
+               //  System.out.println("Other! found (name = " + attributeName + ")");
+               entry = new OtherEntry(_byteReader, attributeNameIndex, length);
+            }
+            attributePoolEntries.add(entry);
+         }
+      }
+
+      CodeEntry getCodeEntry() {
+         return (codeEntry);
+      }
+
+      DeprecatedEntry getDeprecatedEntry() {
+         return (deprecatedEntry);
+      }
+
+      ExceptionEntry getExceptionEntry() {
+         return (exceptionEntry);
+      }
+
+      LineNumberTableEntry getLineNumberTableEntry() {
+         return (lineNumberTableEntry);
+      }
+
+      LocalVariableTableEntry getLocalVariableTableEntry() {
+         return (localVariableTableEntry);
+      }
+
+      SourceFileEntry getSourceFileEntry() {
+         return (sourceFileEntry);
+      }
+
+      SyntheticEntry getSyntheticEntry() {
+         return (syntheticEntry);
+      }
+
+      RuntimeAnnotationsEntry getRuntimeInvisibleAnnotationsEntry() {
+         return (runtimeInvisibleAnnotationsEntry);
+      }
+
+      RuntimeAnnotationsEntry getRuntimeVisibleAnnotationsEntry() {
+         return (runtimeVisibleAnnotationsEntry);
+      }
+
+   }
+
+   static ClassLoader classModelLoader = ClassModel.class.getClassLoader();
+
+   class ClassModelField{
+      private int fieldAccessFlags;
+
+      AttributePool fieldAttributePool;
+
+      private int descriptorIndex;
+
+      private int index;
+
+      private int nameIndex;
+
+      ClassModelField(ByteReader _byteReader, int _index) {
+         index = _index;
+         fieldAccessFlags = _byteReader.u2();
+         nameIndex = _byteReader.u2();
+         descriptorIndex = _byteReader.u2();
+         fieldAttributePool = new AttributePool(_byteReader);
+      }
+
+      int getAccessFlags() {
+         return (fieldAccessFlags);
+      }
+
+      AttributePool getAttributePool() {
+         return (fieldAttributePool);
+      }
+
+      String getDescriptor() {
+         return (getDescriptorUTF8Entry().getUTF8());
+      }
+
+      int getDescriptorIndex() {
+         return (descriptorIndex);
+      }
+
+      ConstantPool.UTF8Entry getDescriptorUTF8Entry() {
+         return (constantPool.getUTF8Entry(descriptorIndex));
+      }
+
+      int getIndex() {
+         return (index);
+      }
+
+      String getName() {
+         return (getNameUTF8Entry().getUTF8());
+      }
+
+      int getNameIndex() {
+         return (nameIndex);
+      }
+
+      ConstantPool.UTF8Entry getNameUTF8Entry() {
+         return (constantPool.getUTF8Entry(nameIndex));
+      }
+
+      Class<?> getDeclaringClass() {
+         String clazzName = getDescriptor().replaceAll("^L", "").replaceAll("/", ".").replaceAll(";$", "");
+         try {
+            return (Class.forName(clazzName, true, classModelLoader));
+         } catch (ClassNotFoundException e) {
+            System.out.println("no class found for " + clazzName);
+            e.printStackTrace();
+            return null;
+         }
+      }
+   }
+
+   class ClassModelMethod{
+
+      private int methodAccessFlags;
+
+      private AttributePool methodAttributePool;
+
+      private int descriptorIndex;
+
+      private int index;
+
+      private int nameIndex;
+
+      private CodeEntry codeEntry;
+
+      ClassModelMethod(ByteReader _byteReader, int _index) {
+         index = _index;
+         methodAccessFlags = _byteReader.u2();
+         nameIndex = _byteReader.u2();
+         descriptorIndex = _byteReader.u2();
+         methodAttributePool = new AttributePool(_byteReader);
+         codeEntry = methodAttributePool.getCodeEntry();
+      }
+
+      int getAccessFlags() {
+         return (methodAccessFlags);
+      }
+
+      AttributePool getAttributePool() {
+         return (methodAttributePool);
+      }
+
+      AttributePool.CodeEntry getCodeEntry() {
+         return (methodAttributePool.getCodeEntry());
+      }
+
+      String getDescriptor() {
+         return (getDescriptorUTF8Entry().getUTF8());
+      }
+
+      int getDescriptorIndex() {
+         return (descriptorIndex);
+      }
+
+      ConstantPool.UTF8Entry getDescriptorUTF8Entry() {
+         return (constantPool.getUTF8Entry(descriptorIndex));
+      }
+
+      int getIndex() {
+         return (index);
+      }
+
+      String getName() {
+         return (getNameUTF8Entry().getUTF8());
+      }
+
+      int getNameIndex() {
+         return (nameIndex);
+      }
+
+      ConstantPool.UTF8Entry getNameUTF8Entry() {
+         return (constantPool.getUTF8Entry(nameIndex));
+      }
+
+      ConstantPool getConstantPool() {
+         return (constantPool);
+      }
+
+      AttributePool.LineNumberTableEntry getLineNumberTableEntry() {
+         return (getAttributePool().codeEntry.codeEntryAttributePool.lineNumberTableEntry);
+      }
+
+      AttributePool.LocalVariableTableEntry getLocalVariableTableEntry() {
+         return (getAttributePool().codeEntry.codeEntryAttributePool.localVariableTableEntry);
+      }
+
+      LocalVariableTableEntry.LocalVariableInfo getLocalVariable(int _pc, int _index) {
+         return (getLocalVariableTableEntry().getVariable(_pc, _index));
+      }
+
+      byte[] getCode() {
+         return (codeEntry.getCode());
+      }
+
+      ClassModel getClassModel() {
+         return (ClassModel.this);
+      }
+
+   }
+
+   class ClassModelInterface{
+      private int interfaceIndex;
+
+      ClassModelInterface(ByteReader _byteReader) {
+         interfaceIndex = _byteReader.u2();
+      }
+
+      ConstantPool.ClassEntry getClassEntry() {
+         return (constantPool.getClassEntry(interfaceIndex));
+      }
+
+      int getInterfaceIndex() {
+         return (interfaceIndex);
+      }
+
+   }
+
+   private Class<?> clazz;
+
+   /**
+    * We extract the class's classloader and name and delegate to private parse method.
+    * @param _class The class we wish to model
+    * @throws ClassParseException
+    */
+   void parse(Class<?> _class) throws ClassParseException {
+
+      clazz = _class;
+      parse(_class.getClassLoader(), _class.getName());
+   }
+
+   /**
+    * Populate this model by parsing a given classfile from the given classloader.
+    * 
+    * We create a ByteReader (wrapper around the bytes representing the classfile) and pass it to local inner classes to handle the various sections of the class file. 
+    * 
+    * @see ByteReader
+    * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/ClassFileFormat-Java5.pdf">Java 5 Class File Format</a>
+    * @param _classLoader The classloader to access the classfile
+    * @param _className The name of the class to load (we convert '.' to '/' and append ".class" so you don't have to).
+    * @throws ClassParseException
+    */
+   private void parse(ClassLoader _classLoader, String _className) throws ClassParseException {
+
+      ByteReader byteReader = new ByteReader(_classLoader.getResourceAsStream(_className.replace('.', '/') + ".class"));
+      magic = byteReader.u4();
+      minorVersion = byteReader.u2();
+      majorVersion = byteReader.u2();
+      constantPool = new ConstantPool(byteReader);
+
+      accessFlags = byteReader.u2();
+      thisClassConstantPoolIndex = byteReader.u2();
+      superClassConstantPoolIndex = byteReader.u2();
+
+      int interfaceCount = byteReader.u2();
+      for (int i = 0; i < interfaceCount; i++) {
+         ClassModelInterface iface = new ClassModelInterface(byteReader);
+         interfaces.add(iface);
+
+      }
+
+      int fieldCount = byteReader.u2();
+      for (int i = 0; i < fieldCount; i++) {
+         ClassModelField field = new ClassModelField(byteReader, i);
+         fields.add(field);
+
+      }
+
+      int methodPoolLength = byteReader.u2();
+      for (int i = 0; i < methodPoolLength; i++) {
+         ClassModelMethod method = new ClassModelMethod(byteReader, i);
+         methods.add(method);
+
+      }
+
+      attributePool = new AttributePool(byteReader);
+
+   }
+
+   int getMagic() {
+      return (magic);
+   }
+
+   int getMajorVersion() {
+      return (majorVersion);
+   }
+
+   int getMinorVersion() {
+      return (minorVersion);
+   }
+
+   int getAccessFlags() {
+      return (accessFlags);
+   }
+
+   ConstantPool getConstantPool() {
+      return (constantPool);
+   }
+
+   int getThisClassConstantPoolIndex() {
+      return (thisClassConstantPoolIndex);
+   }
+
+   int getSuperClassConstantPoolIndex() {
+      return (superClassConstantPoolIndex);
+   }
+
+   AttributePool getAttributePool() {
+      return (attributePool);
+   }
+
+   ClassModelField getField(String _name, String _descriptor) {
+      for (ClassModelField entry : fields) {
+         if (entry.getName().equals(_name) && entry.getDescriptor().equals(_descriptor)) {
+            return (entry);
+         }
+      }
+      return superClazz.getField(_name, _descriptor);
+   }
+
+   ClassModelField getField(String _name) {
+      for (ClassModelField entry : fields) {
+         if (entry.getName().equals(_name)) {
+            return (entry);
+         }
+      }
+      return superClazz.getField(_name);
+   }
+
+   ClassModelMethod getMethod(String _name, String _descriptor) {
+      for (ClassModelMethod entry : methods) {
+         if (entry.getName().equals(_name) && entry.getDescriptor().equals(_descriptor)) {
+            return (entry);
+         }
+      }
+      return superClazz != null ? superClazz.getMethod(_name, _descriptor) : (null);
+   }
+
+   List<ClassModelField> getFieldPoolEntries() {
+      return (fields);
+   }
+
+   /**
+    * Look up a ConstantPool MethodEntry and return the corresponding Method.  
+    * 
+    * @param _methodEntry The ConstantPool MethodEntry we want.
+    * @param _isSpecial True if we wish to delegate to super (to support <code>super.foo()</code>)
+    * 
+    * @return The Method or null if we fail to locate a given method.
+    */
+   ClassModelMethod getMethod(MethodEntry _methodEntry, boolean _isSpecial) {
+      String entryClassNameInDotForm = _methodEntry.getClassEntry().getNameUTF8Entry().getUTF8().replace('/', '.');
+
+      // Shortcut direct calls to supers to allow "foo() { super.foo() }" type stuff to work
+      if (_isSpecial && (superClazz != null) && superClazz.isSuperClass(entryClassNameInDotForm)) {
+         if (logger.isLoggable(Level.FINE)) {
+            logger.fine("going to look in super:" + superClazz.getClassWeAreModelling().getName() + " on behalf of "
+                  + entryClassNameInDotForm);
+         }
+         return superClazz.getMethod(_methodEntry, false);
+      }
+
+      for (ClassModelMethod entry : methods) {
+         if (entry.getName().equals(_methodEntry.getNameAndTypeEntry().getNameUTF8Entry().getUTF8())
+               && entry.getDescriptor().equals(_methodEntry.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8())) {
+            if (logger.isLoggable(Level.FINE)) {
+               logger.fine("Found " + clazz.getName() + "." + entry.getName() + " " + entry.getDescriptor() + " for "
+                     + entryClassNameInDotForm);
+            }
+            return (entry);
+         }
+      }
+
+      return superClazz != null ? superClazz.getMethod(_methodEntry, false) : (null);
+   }
+
+   /**
+    * Create a MethodModel for a given method name and signature.
+    * 
+    * @param _name
+    * @param _signature
+    * @return 
+    * @throws AparapiException
+    */
+
+   MethodModel getMethodModel(String _name, String _signature) throws AparapiException {
+      ClassModelMethod method = getMethod(_name, _signature);
+      return new MethodModel(method);
+   }
+
+   // These fields use for accessor conversion
+   private ArrayList<FieldEntry> structMembers = new ArrayList<FieldEntry>();
+
+   private ArrayList<Long> structMemberOffsets = new ArrayList<Long>();
+
+   private ArrayList<TypeSpec> structMemberTypes = new ArrayList<TypeSpec>();
+
+   private int totalStructSize = 0;
+
+   ArrayList<FieldEntry> getStructMembers() {
+      return structMembers;
+   }
+
+   ArrayList<Long> getStructMemberOffsets() {
+      return structMemberOffsets;
+   }
+
+   ArrayList<TypeSpec> getStructMemberTypes() {
+      return structMemberTypes;
+   }
+
+   int getTotalStructSize() {
+      return totalStructSize;
+   }
+
+   void setTotalStructSize(int x) {
+      totalStructSize = x;
+   }
+
+   private Entrypoint getEntrypoint(String _entrypointName, String _descriptor, Object _k) throws AparapiException {
+      MethodModel method = getMethodModel(_entrypointName, _descriptor);
+      return (new Entrypoint(this, method, _k));
+   }
+
+   Class<?> getClassWeAreModelling() {
+      return clazz;
+   }
+
+   public Entrypoint getEntrypoint(String _entrypointName, Object _k) throws AparapiException {
+      return (getEntrypoint(_entrypointName, "()V", _k));
+   }
+
+   public Entrypoint getEntrypoint() throws AparapiException {
+      return (getEntrypoint("run", "()V", null));
+   }
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/ClassParseException.java b/com.amd.aparapi/src/java/com/amd/aparapi/ClassParseException.java
new file mode 100644
index 00000000..25420161
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/ClassParseException.java
@@ -0,0 +1,129 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+/**
+ * We throw <code>ClassParseException</code>s (derived from <code>AparapiException</code>) if we encounter any Aparapi unfriendly 
+ * constructs.  This allows us to <strong>fail fast</strong>.
+ * 
+ * @see com.amd.aparapi.AparapiException
+ *
+ * @author gfrost
+ *
+ */
+@SuppressWarnings("serial") public class ClassParseException extends AparapiException{
+   public static enum TYPE {
+      NONE("none"), //
+      ARRAY_RETURN("We don't support areturn instructions"), //
+      PUTFIELD("We don't support putstatic instructions"), //
+      INVOKESTATIC("We don't support invokestatic instructions"), //
+      INVOKEINTERFACE("We don't support invokeinterface instructions"), //
+      GETSTATIC("We don't support getstatic instructions"), //
+      ATHROW("We don't support athrow instructions"), //
+      SYNCHRONIZE("We don't support monitorenter or monitorexit instructions"), //
+      NEW("We don't support new instructions"), //
+      CHARARRAY("We don't support java char array accesses"), //
+      ARRAYALIAS("We don't support copying refs in kernels"), //
+      ACCESSTOCHARFIELD("We don't support java char type"), //
+      SWITCH("We don't support lookupswitch or tableswitch instructions"), //
+      METHODARRAYARG("We don't support passing arrays as method args"), //
+      RECURSION("We don't support recursion"), //
+      UNSUPPORTEDBYTECODE("This bytecode is not supported"), //
+      OPERANDCONSUMERPRODUCERMISSMATCH("Detected an non-reducable operand consumer/producer mismatch"), //
+      BADGETTERTYPEMISMATCH("Getter return type does not match field var type"), //
+      BADGETTERNAMEMISMATCH("Getter name does not match fiels name"), //
+      BADGETTERNAMENOTFOUND("Getter not found"), //
+      BADSETTERTYPEMISMATCH("Setter arg type does not match field var type"), // 
+      EXCEPTION("We don't support catch blocks"), //
+      ARRAYLOCALVARIABLE("Found an array local variable which assumes that we will alias a field array"), //
+      CHARLOCALVARIABLE("Found a char local variable"), //
+      CONFUSINGBRANCHESPOSSIBLYCONTINUE("we don't support continue"), //
+      CONFUSINGBRANCHESPOSSIBLYBREAK("we don't support break"), //
+      OBJECTFIELDREFERENCE("Using java objects inside kernels is not supported"), //
+      OBJECTARRAYFIELDREFERENCE("Object array elements cannot contain"), //
+      OVERRIDENFIELD("Found overidden field"), //
+      LOCALARRAYLENGTHACCESS("Found array length access on local array. Might be a result of using ForEach()"), //
+      ACCESSEDOBJECTNONFINAL("Kernel array object member class must be final."), //
+      ACCESSEDOBJECTFIELDNAMECONFLICT("Conflicting fields found in class hierarchy"), //
+      ACCESSEDOBJECTONLYSUPPORTSSIMPLEPUTFIELD("We don't support putfield instructions beyond simple setters"), //
+      ACCESSEDOBJECTSETTERARRAY("Passing array arguments to Intrinsics in expression form is not supported");
+      private String description;
+
+      TYPE(String _description) {
+         description = _description;
+      }
+
+      public String getDescription() {
+         return (description);
+      }
+   };
+
+   Instruction instruction;
+
+   TYPE type;
+
+   ClassParseException(TYPE _type) {
+      super(_type.getDescription());
+      type = _type;
+      instruction = null;
+   }
+
+   ClassParseException(Instruction _instruction, TYPE _type) {
+      super("@" + _instruction.getThisPC() + " " + _instruction.getByteCode() + " " + _type.getDescription());
+      type = _type;
+      instruction = _instruction;
+   }
+
+   ClassParseException(TYPE _type, String _methodName) {
+      super("@" + _methodName + " " + _type.getDescription());
+      type = _type;
+      instruction = null;
+   }
+
+   public Instruction getInstruction() {
+      return (instruction);
+   }
+
+   public TYPE getType() {
+      return (type);
+   }
+
+   ClassParseException(Throwable _t) {
+      super(_t);
+   }
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/CodeGenException.java b/com.amd.aparapi/src/java/com/amd/aparapi/CodeGenException.java
new file mode 100644
index 00000000..c52e50ea
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/CodeGenException.java
@@ -0,0 +1,46 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+@SuppressWarnings("serial") class CodeGenException extends AparapiException{
+
+   CodeGenException(String msg) {
+      super(msg);
+   }
+
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/Config.java b/com.amd.aparapi/src/java/com/amd/aparapi/Config.java
new file mode 100644
index 00000000..57b36ff3
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/Config.java
@@ -0,0 +1,199 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A central location for holding all runtime configurable properties as well as logging configuration.
+ * 
+ * Ideally we will find all properties used by <code>Aparapi</code> here.  Please consider updating this class if you wish
+ * to add new properties which control <code>Aparapi</code>s behavior. 
+ *
+ * @author gfrost
+ *
+ */
+class Config{
+
+   private static final String propPkgName = Config.class.getPackage().getName();
+
+   static final boolean disableUnsafe = Boolean.getBoolean(propPkgName + ".disableUnsafe");
+
+   /**
+    * Allows the user to request a specific Kernel.EXECUTION_MODE enum value for all Kernels.
+    * 
+    *  Usage -Dcom.amd.aparapi.executionMode={SEQ|JTP|CPU|GPU}
+    *  
+    *  @see com.amd.aparapi.Kernel.EXECUTION_MODE
+    */
+   static final String executionMode = System.getProperty(propPkgName + ".executionMode");
+
+   /**
+    * Allows the user to turn on OpenCL profiling for the JNI/OpenCL layer.
+    * 
+    *  Usage -Dcom.amd.aparapi.enableProfiling={true|false}
+    *  
+    */
+   static final boolean enableProfiling = Boolean.getBoolean(propPkgName + ".enableProfiling");
+
+   /**
+    * Allows the user to request that verbose JNI messages be dumped to stderr.
+    * 
+    *  Usage -Dcom.amd.aparapi.enableVerboseJNI={true|false}
+    *  
+    */
+   static final boolean enableVerboseJNI = Boolean.getBoolean(propPkgName + ".enableVerboseJNI");
+
+   /**
+    * Allows the user to request that the execution mode of each kernel invocation be reported to stdout.
+    * 
+    *  Usage -Dcom.amd.aparapi.enableExecutionModeReporting={true|false}
+    *  
+    */
+   static final boolean enableExecutionModeReporting = Boolean.getBoolean(propPkgName + ".enableExecutionModeReporting");
+
+   /**
+    * Allows the user to request that generated OpenCL code is dumped to standard out.
+    * 
+    *  Usage -Dcom.amd.aparapi.enableShowGeneratedOpenCL={true|false}
+    *  
+    */
+   static final boolean enableShowGeneratedOpenCL = Boolean.getBoolean(propPkgName + ".enableShowGeneratedOpenCL");
+
+   // Pragma/OpenCL codegen related flags
+   static final boolean enableAtomic32 = Boolean.getBoolean(propPkgName + ".enableAtomic32");
+
+   static final boolean enableAtomic64 = Boolean.getBoolean(propPkgName + ".enableAtomic64");
+
+   static final boolean enableByteWrites = Boolean.getBoolean(propPkgName + ".enableByteWrites");
+
+   public static final boolean enableDoubles = Boolean.getBoolean(propPkgName + ".enableDoubles");
+
+   // Debugging related flags
+   static final boolean verboseComparitor = Boolean.getBoolean(propPkgName + ".verboseComparitor");
+
+   static final boolean dumpFlags = Boolean.getBoolean(propPkgName + ".dumpFlags");
+
+   // Individual bytecode support related flags
+   static final boolean enablePUTFIELD = Boolean.getBoolean(propPkgName + ".enable.PUTFIELD");
+
+   static final boolean enableARETURN = !Boolean.getBoolean(propPkgName + ".disable.ARETURN");
+
+   static final boolean enablePUTSTATIC = Boolean.getBoolean(propPkgName + ".enable.PUTSTATIC");
+
+   static final boolean enableGETSTATIC = Boolean.getBoolean(propPkgName + ".enable.GETSTATIC");
+
+   static final boolean enableINVOKESTATIC = Boolean.getBoolean(propPkgName + ".enable.INVOKESTATIC");
+
+   static final boolean enableINVOKEINTERFACE = Boolean.getBoolean(propPkgName + ".enable.INVOKEINTERFACE");
+
+   static final boolean enableMONITOR = Boolean.getBoolean(propPkgName + ".enable.MONITOR");
+
+   static final boolean enableNEW = Boolean.getBoolean(propPkgName + ".enable.NEW");
+
+   static final boolean enableATHROW = Boolean.getBoolean(propPkgName + ".enable.ATHROW");
+
+   static final boolean enableMETHODARRAYPASSING = !Boolean.getBoolean(propPkgName + ".disable.METHODARRAYPASSING");
+
+   static final boolean enableARRAYLENGTH = Boolean.getBoolean(propPkgName + ".enable.ARRAYLENGTH");
+
+   static final boolean enableSWITCH = Boolean.getBoolean(propPkgName + ".enable.SWITCH");
+
+   static final int JTPLocalSizeMultiplier = Integer.getInteger(propPkgName + ".JTP.localSizeMul", 2);
+
+   // Logging setup
+   private static final String logPropName = propPkgName + ".logLevel";
+
+   static String getLoggerName() {
+      return logPropName;
+   }
+
+   static Logger logger = Logger.getLogger(Config.getLoggerName());
+   static {
+
+      try {
+
+         Level level = Level.parse(System.getProperty(getLoggerName(), "WARNING"));
+
+         Handler[] handlers = Logger.getLogger("").getHandlers();
+         for (int index = 0; index < handlers.length; index++) {
+            handlers[index].setLevel(level);
+         }
+
+         logger.setLevel(level);
+
+      } catch (Exception e) {
+         System.out.println("Exception " + e + " in Aparapi logging setup.");
+         e.printStackTrace();
+      }
+
+      if (dumpFlags) {
+         logger.fine("executionMode = " + executionMode);
+
+      }
+   };
+
+   public interface InstructionListener{
+      void showAndTell(String message, Instruction _start, Instruction _instruction);
+   }
+
+   static String instructionListenerClassName = System.getProperty(propPkgName + ".instructionListenerClass");
+
+   static public InstructionListener instructionListener = null;
+   {
+
+      if (instructionListenerClassName != null && !instructionListenerClassName.equals("")) {
+         try {
+            Class<?> instructionListenerClass = Class.forName(instructionListenerClassName);
+            instructionListener = (InstructionListener) instructionListenerClass.newInstance();
+         } catch (ClassNotFoundException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+         } catch (InstantiationException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+         } catch (IllegalAccessException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+         }
+      }
+   }
+
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/Entrypoint.java b/com.amd.aparapi/src/java/com/amd/aparapi/Entrypoint.java
new file mode 100644
index 00000000..38bdbdf1
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/Entrypoint.java
@@ -0,0 +1,867 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.amd.aparapi.ClassModel.ClassModelField;
+import com.amd.aparapi.ClassModel.ClassModelMethod;
+import com.amd.aparapi.ClassModel.ConstantPool.FieldEntry;
+import com.amd.aparapi.ClassModel.ConstantPool.MethodEntry;
+import com.amd.aparapi.ClassModel.ConstantPool.MethodReferenceEntry.Arg;
+import com.amd.aparapi.InstructionSet.AccessArrayElement;
+import com.amd.aparapi.InstructionSet.AccessField;
+import com.amd.aparapi.InstructionSet.AssignToArrayElement;
+import com.amd.aparapi.InstructionSet.AssignToField;
+import com.amd.aparapi.InstructionSet.I_ARRAYLENGTH;
+import com.amd.aparapi.InstructionSet.I_GETFIELD;
+import com.amd.aparapi.InstructionSet.I_INVOKESPECIAL;
+import com.amd.aparapi.InstructionSet.I_INVOKEVIRTUAL;
+import com.amd.aparapi.InstructionSet.MethodCall;
+import com.amd.aparapi.InstructionSet.TypeSpec;
+import com.amd.aparapi.InstructionSet.VirtualMethodCall;
+
+class Entrypoint{
+
+   private static Logger logger = Logger.getLogger(Config.getLoggerName());
+
+   private List<ClassModel.ClassModelField> referencedClassModelFields = new ArrayList<ClassModel.ClassModelField>();
+
+   private List<Field> referencedFields = new ArrayList<Field>();
+
+   private ClassModel classModel;
+
+   private Object kernelInstance = null;
+
+   private boolean fallback = false;
+
+   private Set<String> referencedFieldNames = new LinkedHashSet<String>();
+
+   private Set<String> arrayFieldAssignments = new LinkedHashSet<String>();
+
+   private Set<String> arrayFieldAccesses = new LinkedHashSet<String>();
+
+   // Classes of object array members
+   private HashMap<String, ClassModel> objectArrayFieldsClasses = new HashMap<String, ClassModel>();
+
+   // Supporting classes of object array members like supers
+   private HashMap<String, ClassModel> allFieldsClasses = new HashMap<String, ClassModel>();
+
+   // Keep track of arrays whose length is taken via foo.length
+   private Set<String> arrayFieldArrayLengthUsed = new LinkedHashSet<String>();
+
+   private List<MethodModel> calledMethods = new ArrayList<MethodModel>();
+
+   private MethodModel methodModel;
+
+   /**
+      True is an indication to use the fp64 pragma
+   */
+   private boolean usesDoubles;
+
+   /**
+      True is an indication to use the byte addressable store pragma
+   */
+   private boolean usesByteWrites;
+
+   /**
+      True is an indication to use the atomics pragmas
+   */
+   private boolean usesAtomic32;
+
+   private boolean usesAtomic64;
+
+   boolean requiresDoublePragma() {
+      return usesDoubles;
+   }
+
+   boolean requiresByteAddressableStorePragma() {
+      return usesByteWrites;
+   }
+
+   /* Atomics are detected in Entrypoint */
+   void setRequiresAtomics32Pragma(boolean newVal) {
+      usesAtomic32 = newVal;
+   }
+
+   void setRequiresAtomics64Pragma(boolean newVal) {
+      usesAtomic64 = newVal;
+   }
+
+   boolean requiresAtomic32Pragma() {
+      return usesAtomic32;
+   }
+
+   boolean requiresAtomic64Pragma() {
+      return usesAtomic64;
+   }
+
+   Object getKernelInstance() {
+      return kernelInstance;
+   }
+
+   void setKernelInstance(Object _k) {
+      kernelInstance = _k;
+   }
+
+   Map<String, ClassModel> getObjectArrayFieldsClasses() {
+      return objectArrayFieldsClasses;
+   }
+
+   static Field getFieldFromClassHierarchy(Class<?> _clazz, String _name) throws AparapiException {
+
+      // look in self
+      // if found, done
+
+      // get superclass of curr class
+      // while not found
+      //  get its fields
+      //  if found
+      //   if not private, done
+      //  if private, failure
+      //  if not found, get next superclass
+
+      Field field = null;
+
+      assert _name != null : "_name should not be null";
+
+      if (logger.isLoggable(Level.FINE)) {
+         logger.fine("looking for " + _name + " in " + _clazz.getName());
+      }
+
+      try {
+         field = _clazz.getDeclaredField(_name);
+         Class<?> type = field.getType();
+         if (type.isPrimitive() || type.isArray()) {
+            return field;
+         }
+         if (logger.isLoggable(Level.FINE)) {
+            logger.fine("field type is " + type.getName());
+         }
+         throw new ClassParseException(ClassParseException.TYPE.OBJECTFIELDREFERENCE);
+      } catch (NoSuchFieldException nsfe) {
+         // This should be looger fine...
+         //System.out.println("no " + _name + " in " + _clazz.getName());
+      }
+
+      Class<?> mySuper = _clazz.getSuperclass();
+
+      if (logger.isLoggable(Level.FINE)) {
+         logger.fine("looking for " + _name + " in " + mySuper.getName());
+      }
+
+      // Find better way to do this check
+      while (!mySuper.getName().equals(Kernel.class.getName())) {
+         try {
+            field = mySuper.getDeclaredField(_name);
+            int modifiers = field.getModifiers();
+            if ((Modifier.isStatic(modifiers) == false) && (Modifier.isPrivate(modifiers) == false)) {
+               Class<?> type = field.getType();
+               if (logger.isLoggable(Level.FINE)) {
+                  logger.fine("field type is " + type.getName());
+               }
+               if (type.isPrimitive() || type.isArray()) {
+                  return field;
+               }
+               throw new ClassParseException(ClassParseException.TYPE.OBJECTFIELDREFERENCE);
+            } else {
+               // This should be looger fine...
+               //System.out.println("field " + _name + " not suitable: " + java.lang.reflect.Modifier.toString(modifiers));
+               return null;
+            }
+         } catch (NoSuchFieldException nsfe) {
+            if (logger.isLoggable(Level.FINE)) {
+               logger.fine("no " + _name + " in " + mySuper.getName());
+            }
+            mySuper = mySuper.getSuperclass();
+            assert mySuper != null : "mySuper is null!";
+         }
+      }
+      return null;
+   }
+
+   /*
+    * Update the list of object array member classes and all the superclasses
+    * of those classes and the fields in each class
+    */
+   ClassModel getOrUpdateAllClassAccesses(String className) throws AparapiException {
+      ClassModel memberClassModel = allFieldsClasses.get(className);
+      if (memberClassModel == null) {
+         try {
+            Class<?> memberClass = Class.forName(className);
+
+            // Immediately add this class and all its supers if necessary
+            memberClassModel = new ClassModel(memberClass);
+            if (logger.isLoggable(Level.FINEST)) {
+               logger.finest("adding class " + className);
+            }
+            allFieldsClasses.put(className, memberClassModel);
+            ClassModel superModel = memberClassModel.getSuperClazz();
+            while (superModel != null) {
+               // See if super is already added
+               ClassModel oldSuper = allFieldsClasses.get(superModel.getClassWeAreModelling().getName());
+               if (oldSuper != null) {
+                  if (oldSuper != superModel) {
+                     memberClassModel.replaceSuperClazz(oldSuper);
+                     if (logger.isLoggable(Level.FINEST)) {
+                        logger.finest("replaced super " + oldSuper.getClassWeAreModelling().getName() + " for " + className);
+                     }
+                  }
+               } else {
+                  allFieldsClasses.put(superModel.getClassWeAreModelling().getName(), superModel);
+                  if (logger.isLoggable(Level.FINEST)) {
+                     logger.finest("add new super " + superModel.getClassWeAreModelling().getName() + " for " + className);
+                  }
+               }
+
+               superModel = superModel.getSuperClazz();
+            }
+         } catch (Exception e) {
+            if (logger.isLoggable(Level.INFO)) {
+               logger.info("Cannot find: " + className);
+            }
+            throw new AparapiException(e);
+         }
+      }
+
+      return memberClassModel;
+   }
+
+   ClassModelMethod resolveAccessorCandidate(MethodCall _methodCall, MethodEntry _methodEntry) throws AparapiException {
+      String methodsActualClassName = (_methodEntry.getClassEntry().getNameUTF8Entry().getUTF8()).replace('/', '.');
+
+      if (_methodCall instanceof VirtualMethodCall) {
+         Instruction callInstance = ((VirtualMethodCall) _methodCall).getInstanceReference();
+         if (callInstance instanceof AccessArrayElement) {
+            AccessArrayElement arrayAccess = (AccessArrayElement) callInstance;
+            Instruction refAccess = arrayAccess.getArrayRef();
+            if (refAccess instanceof I_GETFIELD) {
+
+               // It is a call from a member obj array element
+               if (logger.isLoggable(Level.FINE)) {
+                  logger.fine("Looking for class in accessor call: " + methodsActualClassName);
+               }
+               ClassModel memberClassModel = getOrUpdateAllClassAccesses(methodsActualClassName);
+
+               // false = no invokespecial allowed here
+               return memberClassModel.getMethod(_methodEntry, false);
+            }
+         }
+      }
+      return null;
+   }
+
+   /*
+    * Update accessor structures when there is a direct access to an 
+    * obect array element's data members
+    */
+   void updateObjectMemberFieldAccesses(String className, FieldEntry field) throws AparapiException {
+      String accessedFieldName = field.getNameAndTypeEntry().getNameUTF8Entry().getUTF8();
+
+      // Quickly bail if it is a ref
+      if (field.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8().startsWith("L")
+            || field.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8().startsWith("[L")) {
+         throw new ClassParseException(ClassParseException.TYPE.OBJECTARRAYFIELDREFERENCE);
+      }
+
+      if (logger.isLoggable(Level.FINEST)) {
+         logger.finest("Updating access: " + className + " field:" + accessedFieldName);
+      }
+
+      ClassModel memberClassModel = getOrUpdateAllClassAccesses(className);
+      Class<?> memberClass = memberClassModel.getClassWeAreModelling();
+      ClassModel superCandidate = null;
+
+      // We may add this field if no superclass match
+      boolean add = true;
+
+      // No exact match, look for a superclass
+      for (ClassModel c : allFieldsClasses.values()) {
+         if (logger.isLoggable(Level.FINEST)) {
+            logger.finest(" super: " + c.getClassWeAreModelling().getName() + " for " + className);
+         }
+         if (c.isSuperClass(memberClass)) {
+            if (logger.isLoggable(Level.FINE)) {
+               logger.fine("selected super: " + c.getClassWeAreModelling().getName() + " for " + className);
+            }
+            superCandidate = c;
+            break;
+         }
+
+         if (logger.isLoggable(Level.FINEST)) {
+            logger.finest(" no super match for " + memberClass.getName());
+         }
+      }
+
+      // Look at super's fields for a match
+      if (superCandidate != null) {
+         ArrayList<FieldEntry> structMemberSet = superCandidate.getStructMembers();
+         for (FieldEntry f : structMemberSet) {
+            if (f.getNameAndTypeEntry().getNameUTF8Entry().getUTF8().equals(accessedFieldName)
+                  && f.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8().equals(
+                        field.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8())) {
+
+               if (logger.isLoggable(Level.FINE)) {
+                  logger.fine("Found match: " + accessedFieldName + " class: " + field.getClassEntry().getNameUTF8Entry().getUTF8()
+                        + " to class: " + f.getClassEntry().getNameUTF8Entry().getUTF8());
+               }
+
+               if (!f.getClassEntry().getNameUTF8Entry().getUTF8().equals(field.getClassEntry().getNameUTF8Entry().getUTF8())) {
+                  // Look up in class hierarchy to ensure it is the same field
+                  Field superField = getFieldFromClassHierarchy(superCandidate.getClassWeAreModelling(), f.getNameAndTypeEntry()
+                        .getNameUTF8Entry().getUTF8());
+                  Field classField = getFieldFromClassHierarchy(memberClass, f.getNameAndTypeEntry().getNameUTF8Entry().getUTF8());
+                  if (!superField.equals(classField)) {
+                     throw new ClassParseException(ClassParseException.TYPE.OVERRIDENFIELD);
+                  }
+               }
+
+               add = false;
+               break;
+            }
+         }
+      }
+
+      // There was no matching field in the supers, add it to the memberClassModel
+      // if not already there
+      if (add) {
+         boolean found = false;
+         ArrayList<FieldEntry> structMemberSet = memberClassModel.getStructMembers();
+         for (FieldEntry f : structMemberSet) {
+            if (f.getNameAndTypeEntry().getNameUTF8Entry().getUTF8().equals(accessedFieldName)
+                  && f.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8().equals(
+                        field.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8())) {
+               found = true;
+            }
+         }
+         if (!found) {
+            structMemberSet.add(field);
+            if (logger.isLoggable(Level.FINE)) {
+               logger.fine("Adding assigned field " + field.getNameAndTypeEntry().getNameUTF8Entry().getUTF8() + " type: "
+                     + field.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8() + " to "
+                     + memberClassModel.getClassWeAreModelling().getName());
+            }
+         }
+      }
+   }
+
+   Entrypoint(ClassModel _classModel, MethodModel _methodModel, Object _k) throws AparapiException {
+      classModel = _classModel;
+      methodModel = _methodModel;
+      kernelInstance = _k;
+
+      Map<ClassModelMethod, MethodModel> methodMap = new LinkedHashMap<ClassModelMethod, MethodModel>();
+
+      boolean discovered = true;
+      int thisClassIndex = _classModel.getThisClassConstantPoolIndex();//arf
+
+      // Record which pragmas we need to enable
+      if (methodModel.requiresDoublePragma()) {
+         usesDoubles = true;
+         if (logger.isLoggable(Level.FINE)) {
+            logger.fine("Enabling doubles on " + methodModel.getName());
+         }
+
+      }
+      if (methodModel.requiresByteAddressableStorePragma()) {
+         usesByteWrites = true;
+         if (logger.isLoggable(Level.FINE)) {
+            logger.fine("Enabling byte addressable on " + methodModel.getName());
+         }
+      }
+
+      for (MethodCall methodCall : methodModel.getMethodCalls()) {
+         MethodEntry methodEntry = methodCall.getConstantPoolMethodEntry();
+         if (logger.isLoggable(Level.FINE)) {
+            if (methodCall instanceof I_INVOKESPECIAL) {
+               logger.fine("Method call to super: " + methodEntry);
+            } else if (thisClassIndex != methodEntry.getClassIndex()) {
+               logger.fine("Method call to ??: " + methodEntry);
+            } else {
+               logger.fine("Method call in kernel class: " + methodEntry);
+            }
+         }
+
+         ClassModelMethod m = classModel.getMethod(methodEntry, (methodCall instanceof I_INVOKESPECIAL) ? true : false);
+
+         // Did not find method in this class or supers. Look for data member object arrays
+         if (m == null) {
+            m = resolveAccessorCandidate(methodCall, methodEntry);
+         }
+
+         if (m != null && !methodMap.keySet().contains(m)) {
+            MethodModel target = new MethodModel(m, this);
+            methodMap.put(m, target);
+            methodModel.getCalledMethods().add(target);
+            discovered = true;
+         }
+      }
+
+      // methodMap now contains a list of method called by run itself().
+      // Walk the whole graph of called methods and add them to the methodMap
+      while (!fallback && discovered) {
+         discovered = false;
+         for (MethodModel mm : new ArrayList<MethodModel>(methodMap.values())) {
+            for (MethodCall methodCall : mm.getMethodCalls()) {
+               MethodEntry methodEntry = methodCall.getConstantPoolMethodEntry();
+
+               if (logger.isLoggable(Level.FINE)) {
+                  logger.fine("Looking for: " + methodEntry + " called by " + mm.getMethod().getName());
+               }
+
+               ClassModelMethod m = classModel.getMethod(methodEntry, (methodCall instanceof I_INVOKESPECIAL) ? true : false);
+
+               // Did not find method in this class or supers. Look for data member object arrays
+               if (m == null) {
+                  m = resolveAccessorCandidate(methodCall, methodEntry);
+               }
+
+               // Look for a intra-object call in a object member
+               if (m == null) {
+                  for (ClassModel c : allFieldsClasses.values()) {
+                     if (c.getClassWeAreModelling().getName().equals(
+                           methodEntry.getClassEntry().getNameUTF8Entry().getUTF8().replace('/', '.'))) {
+                        m = c.getMethod(methodEntry, (methodCall instanceof I_INVOKESPECIAL) ? true : false);
+                        assert m != null;
+                        break;
+                     }
+                  }
+               }
+
+               if (m != null) {
+                  MethodModel target = null;
+                  if (methodMap.keySet().contains(m)) {
+                     // we remove and then add again.  Because this is a LinkedHashMap this 
+                     // places this at the end of the list underlying the map
+                     // then when we reverse the collection (below) we get the method 
+                     // declarations in the correct order.  We are trying to avoid creating forward references
+                     target = methodMap.remove(m);
+                     if (logger.isLoggable(Level.FINE)) {
+                        logger.fine("repositioning : " + m.getClassModel().getClassWeAreModelling().getName() + " " + m.getName()
+                              + " " + m.getDescriptor());
+                     }
+                  } else {
+                     target = new MethodModel(m, this);
+                     discovered = true;
+                  }
+                  methodMap.put(m, target);
+                  // Build graph of call targets to look for recursion
+                  mm.getCalledMethods().add(target);
+               }
+            }
+         }
+      }
+
+      methodModel.checkForRecursion(new HashSet<MethodModel>());
+
+      if (logger.isLoggable(Level.FINE)) {
+         logger.fine("fallback=" + fallback);
+      }
+
+      if (!fallback) {
+         calledMethods.addAll(methodMap.values());
+         Collections.reverse(calledMethods);
+         List<MethodModel> methods = new ArrayList<MethodModel>(calledMethods);
+
+         // add method to the calledMethods so we can include in this list
+         methods.add(methodModel);
+         Set<String> fieldAssignments = new HashSet<String>();
+
+         Set<String> fieldAccesses = new HashSet<String>();
+
+         for (MethodModel methodModel : methods) {
+
+            // Record which pragmas we need to enable
+            if (methodModel.requiresDoublePragma()) {
+               usesDoubles = true;
+               if (logger.isLoggable(Level.FINE)) {
+                  logger.fine("Enabling doubles on " + methodModel.getName());
+               }
+
+            }
+            if (methodModel.requiresByteAddressableStorePragma()) {
+               usesByteWrites = true;
+               if (logger.isLoggable(Level.FINE)) {
+                  logger.fine("Enabling byte addressable on " + methodModel.getName());
+               }
+            }
+
+            for (Instruction instruction = methodModel.getPCHead(); instruction != null; instruction = instruction.getNextPC()) {
+
+               if (instruction instanceof AssignToArrayElement) {
+                  AssignToArrayElement assignment = (AssignToArrayElement) instruction;
+
+                  Instruction arrayRef = assignment.getArrayRef();
+                  if (arrayRef instanceof I_GETFIELD) {
+                     I_GETFIELD getField = (I_GETFIELD) arrayRef;
+                     FieldEntry field = getField.getConstantPoolFieldEntry();
+                     String assignedArrayFieldName = field.getNameAndTypeEntry().getNameUTF8Entry().getUTF8();
+                     arrayFieldAssignments.add(assignedArrayFieldName);
+                     referencedFieldNames.add(assignedArrayFieldName);
+
+                  }
+               } else if (instruction instanceof AccessArrayElement) {
+                  AccessArrayElement access = (AccessArrayElement) instruction;
+
+                  Instruction arrayRef = access.getArrayRef();
+                  if (arrayRef instanceof I_GETFIELD) {
+                     I_GETFIELD getField = (I_GETFIELD) arrayRef;
+                     FieldEntry field = getField.getConstantPoolFieldEntry();
+                     String accessedArrayFieldName = field.getNameAndTypeEntry().getNameUTF8Entry().getUTF8();
+                     arrayFieldAccesses.add(accessedArrayFieldName);
+                     referencedFieldNames.add(accessedArrayFieldName);
+
+                  }
+               } else if (instruction instanceof I_ARRAYLENGTH) {
+                  if (!(instruction.getFirstChild() instanceof AccessField)) {
+                     throw new ClassParseException(ClassParseException.TYPE.LOCALARRAYLENGTHACCESS);
+                  }
+                  AccessField child = (AccessField) instruction.getFirstChild();
+                  String arrayName = child.getConstantPoolFieldEntry().getNameAndTypeEntry().getNameUTF8Entry().getUTF8();
+                  arrayFieldArrayLengthUsed.add(arrayName);
+                  if (logger.isLoggable(Level.FINE)) {
+                     logger.fine("Noted arraylength in " + methodModel.getName() + " on " + arrayName);
+                  }
+               } else if (instruction instanceof AccessField) {
+                  AccessField access = (AccessField) instruction;
+                  FieldEntry field = access.getConstantPoolFieldEntry();
+                  String accessedFieldName = field.getNameAndTypeEntry().getNameUTF8Entry().getUTF8();
+                  fieldAccesses.add(accessedFieldName);
+                  referencedFieldNames.add(accessedFieldName);
+
+                  String signature = field.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8();
+                  if (logger.isLoggable(Level.FINE)) {
+                     logger.fine("AccessField field type= " + signature + " in " + methodModel.getName());
+                  }
+
+                  // Add the class model for the referenced obj array
+                  if (signature.startsWith("[L")) {
+                     // Turn [Lcom/amd/javalabs/opencl/demo/DummyOOA; into com.amd.javalabs.opencl.demo.DummyOOA for example
+                     String className = (signature.substring(2, signature.length() - 1)).replace("/", ".");
+                     ClassModel arrayFieldModel = getOrUpdateAllClassAccesses(className);
+                     if (arrayFieldModel != null) {
+                        Class<?> memberClass = arrayFieldModel.getClassWeAreModelling();
+                        int modifiers = memberClass.getModifiers();
+                        if (!Modifier.isFinal(modifiers)) {
+                           throw new ClassParseException(ClassParseException.TYPE.ACCESSEDOBJECTNONFINAL);
+                        }
+
+                        ClassModel refModel = objectArrayFieldsClasses.get(className);
+                        if (refModel == null) {
+
+                           // Verify no other member with common parent
+                           for (ClassModel memberObjClass : objectArrayFieldsClasses.values()) {
+                              ClassModel superModel = memberObjClass;
+                              while (superModel != null) {
+                                 if (superModel.isSuperClass(memberClass)) {
+                                    throw new ClassParseException(ClassParseException.TYPE.ACCESSEDOBJECTFIELDNAMECONFLICT);
+                                 }
+                                 superModel = superModel.getSuperClazz();
+                              }
+                           }
+
+                           objectArrayFieldsClasses.put(className, arrayFieldModel);
+                           if (logger.isLoggable(Level.FINE)) {
+                              logger.fine("adding class to objectArrayFields: " + className);
+                           }
+                        }
+                     }
+                  } else {
+                     String className = (field.getClassEntry().getNameUTF8Entry().getUTF8()).replace("/", ".");
+                     // Look for object data member access
+                     if (!className.equals(this.getClassModel().getClassWeAreModelling().getName())
+                           && getFieldFromClassHierarchy(getClassModel().getClassWeAreModelling(), accessedFieldName) == null) {
+                        updateObjectMemberFieldAccesses(className, field);
+                     }
+                  }
+
+               } else if (instruction instanceof AssignToField) {
+                  AssignToField assignment = (AssignToField) instruction;
+                  FieldEntry field = assignment.getConstantPoolFieldEntry();
+                  String assignedFieldName = field.getNameAndTypeEntry().getNameUTF8Entry().getUTF8();
+                  fieldAssignments.add(assignedFieldName);
+                  referencedFieldNames.add(assignedFieldName);
+
+                  String className = (field.getClassEntry().getNameUTF8Entry().getUTF8()).replace("/", ".");
+                  // Look for object data member access
+                  if (!className.equals(this.getClassModel().getClassWeAreModelling().getName())
+                        && getFieldFromClassHierarchy(getClassModel().getClassWeAreModelling(), assignedFieldName) == null) {
+                     updateObjectMemberFieldAccesses(className, field);
+                  } else {
+
+                     if ((!Config.enablePUTFIELD) && methodModel.methodUsesPutfield() && !methodModel.isSetter()) {
+                        throw new ClassParseException(ClassParseException.TYPE.ACCESSEDOBJECTONLYSUPPORTSSIMPLEPUTFIELD);
+                     }
+
+                  }
+
+               } else if (instruction instanceof I_INVOKEVIRTUAL) {
+                  I_INVOKEVIRTUAL invokeInstruction = (I_INVOKEVIRTUAL) instruction;
+                  MethodEntry methodEntry = invokeInstruction.getConstantPoolMethodEntry();
+                  if (Kernel.isMappedMethod(methodEntry)) { //only do this for intrinsics
+
+                     if (Kernel.usesAtomic32(methodEntry)) {
+                        setRequiresAtomics32Pragma(true);
+                     }
+
+                     Arg methodArgs[] = methodEntry.getArgs();
+                     if (methodArgs.length > 0 && methodArgs[0].isArray()) { //currently array arg can only take slot 0
+                        Instruction arrInstruction = invokeInstruction.getArg(0);
+                        if (arrInstruction instanceof AccessField) {
+                           AccessField access = (AccessField) arrInstruction;
+                           FieldEntry field = access.getConstantPoolFieldEntry();
+                           String accessedFieldName = field.getNameAndTypeEntry().getNameUTF8Entry().getUTF8();
+                           arrayFieldAssignments.add(accessedFieldName);
+                           referencedFieldNames.add(accessedFieldName);
+                        } else {
+                           throw new ClassParseException(ClassParseException.TYPE.ACCESSEDOBJECTSETTERARRAY);
+                        }
+                     }
+                  }
+
+               }
+            }
+         }
+
+         for (String referencedFieldName : referencedFieldNames) {
+
+            try {
+               Class<?> clazz = classModel.getClassWeAreModelling();
+               Field field = getFieldFromClassHierarchy(clazz, referencedFieldName);
+               if (field != null) {
+                  referencedFields.add(field);
+                  ClassModelField ff = classModel.getField(referencedFieldName);
+                  assert ff != null : "ff should not be null for " + clazz.getName() + "." + referencedFieldName;
+                  referencedClassModelFields.add(ff);
+               }
+            } catch (SecurityException e) {
+               e.printStackTrace();
+            }
+         }
+
+         // Build data needed for oop form transforms if necessary
+         if (!objectArrayFieldsClasses.keySet().isEmpty()) {
+
+            for (ClassModel memberObjClass : objectArrayFieldsClasses.values()) {
+
+               // At this point we have already done the field override safety check, so 
+               // add all the superclass fields into the kernel member class to be
+               // sorted by size and emitted into the struct
+               ClassModel superModel = memberObjClass.getSuperClazz();
+               while (superModel != null) {
+                  if (logger.isLoggable(Level.FINEST)) {
+                     logger.finest("adding = " + superModel.getClassWeAreModelling().getName() + " fields into "
+                           + memberObjClass.getClassWeAreModelling().getName());
+                  }
+                  memberObjClass.getStructMembers().addAll(superModel.getStructMembers());
+                  superModel = superModel.getSuperClazz();
+               }
+            }
+
+            // Sort fields of each class biggest->smallest
+            final Comparator<FieldEntry> fieldSizeComparator = new Comparator<FieldEntry>(){
+               public int compare(FieldEntry aa, FieldEntry bb) {
+                  String aType = aa.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8();
+                  String bType = bb.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8();
+
+                  // Booleans get converted down to bytes
+                  int aSize = InstructionSet.TypeSpec.valueOf(aType.equals("Z") ? "B" : aType).getSize();
+                  int bSize = InstructionSet.TypeSpec.valueOf(bType.equals("Z") ? "B" : bType).getSize();
+
+                  if (logger.isLoggable(Level.FINEST)) {
+                     logger.finest("aType= " + aType + " aSize= " + aSize + " . . bType= " + bType + " bSize= " + bSize);
+                  }
+
+                  // Note this is sorting in reverse order so the biggest is first
+                  if (aSize > bSize) {
+                     return -1;
+                  } else if (aSize == bSize) {
+                     return 0;
+                  } else {
+                     return 1;
+                  }
+               }
+            };
+
+            for (ClassModel c : objectArrayFieldsClasses.values()) {
+               ArrayList<FieldEntry> fields = c.getStructMembers();
+               if (fields.size() > 0) {
+                  Collections.sort(fields, fieldSizeComparator);
+
+                  // Now compute the total size for the struct
+                  int totalSize = 0;
+                  int alignTo = 0;
+
+                  for (FieldEntry f : fields) {
+                     // Record field offset for use while copying
+                     // Get field we will copy out of the kernel member object
+                     Field rfield = getFieldFromClassHierarchy(c.getClassWeAreModelling(), f.getNameAndTypeEntry()
+                           .getNameUTF8Entry().getUTF8());
+
+                     c.getStructMemberOffsets().add(UnsafeWrapper.objectFieldOffset(rfield));
+
+                     String fType = f.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8();
+                     //c.getStructMemberTypes().add(TypeSpec.valueOf(fType.equals("Z") ? "B" : fType));
+                     c.getStructMemberTypes().add(TypeSpec.valueOf(fType));
+                     int fSize = TypeSpec.valueOf(fType.equals("Z") ? "B" : fType).getSize();
+                     if (fSize > alignTo) {
+                        alignTo = fSize;
+                     }
+
+                     totalSize += fSize;
+                     if (logger.isLoggable(Level.FINEST)) {
+                        logger.finest("Field = " + f.getNameAndTypeEntry().getNameUTF8Entry().getUTF8() + " size=" + fSize
+                              + " totalSize=" + totalSize);
+                     }
+                  }
+
+                  // compute total size for OpenCL buffer
+                  int totalStructSize = 0;
+                  if (totalSize % alignTo == 0) {
+                     totalStructSize = totalSize;
+                  } else {
+                     // Pad up if necessary
+                     totalStructSize = ((totalSize / alignTo) + 1) * alignTo;
+                  }
+                  c.setTotalStructSize(totalStructSize);
+               }
+            }
+         }
+
+      }
+   }
+
+   boolean shouldFallback() {
+      return (fallback);
+   }
+
+   List<ClassModel.ClassModelField> getReferencedClassModelFields() {
+      return (referencedClassModelFields);
+   }
+
+   List<Field> getReferencedFields() {
+      return (referencedFields);
+   }
+
+   List<MethodModel> getCalledMethods() {
+      return calledMethods;
+   }
+
+   Set<String> getReferencedFieldNames() {
+      return (referencedFieldNames);
+   }
+
+   Set<String> getArrayFieldAssignments() {
+      return (arrayFieldAssignments);
+   }
+
+   Set<String> getArrayFieldAccesses() {
+      return (arrayFieldAccesses);
+   }
+
+   Set<String> getArrayFieldArrayLengthUsed() {
+      return (arrayFieldArrayLengthUsed);
+   }
+
+   MethodModel getMethodModel() {
+      return (methodModel);
+   }
+
+   ClassModel getClassModel() {
+      return (classModel);
+   }
+
+   /*
+    * Return the best call target MethodModel by looking in the class hierarchy
+    * @param _methodEntry MethodEntry for the desired target
+    * @return the fully qualified name such as "com_amd_javalabs_opencl_demo_PaternityTest$SimpleKernel__actuallyDoIt"
+    */
+   MethodModel getCallTarget(MethodEntry _methodEntry, boolean _isSpecial) {
+      ClassModelMethod target = getClassModel().getMethod(_methodEntry, _isSpecial);
+
+      if (logger.isLoggable(Level.FINE) && target == null) {
+         logger.info("Did not find call target: " + _methodEntry + " in " + getClassModel().getClassWeAreModelling().getName());
+      }
+
+      if (target == null) {
+         // Look for member obj accessor calls
+         for (ClassModel memberObjClass : objectArrayFieldsClasses.values()) {
+            String entryClassNameInDotForm = _methodEntry.getClassEntry().getNameUTF8Entry().getUTF8().replace('/', '.');
+            if (entryClassNameInDotForm.equals(memberObjClass.getClassWeAreModelling().getName())) {
+               if (logger.isLoggable(Level.FINE)) {
+                  logger.info("Searching for call target: " + _methodEntry + " in "
+                        + memberObjClass.getClassWeAreModelling().getName());
+               }
+
+               target = memberObjClass.getMethod(_methodEntry, false);
+               if (target != null) {
+                  break;
+               }
+            }
+         }
+      }
+
+      if (target != null) {
+         for (MethodModel m : calledMethods) {
+            if (m.getMethod() == target) {
+               if (logger.isLoggable(Level.FINE)) {
+                  logger.fine("selected from called methods = " + m.getName());
+               }
+               return m;
+            }
+         }
+      }
+
+      assert target == null : "Should not have missed a method in calledMethods";
+
+      return null;
+   }
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/ExpressionList.java b/com.amd.aparapi/src/java/com/amd/aparapi/ExpressionList.java
new file mode 100644
index 00000000..9b884220
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/ExpressionList.java
@@ -0,0 +1,942 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.amd.aparapi.ClassModel.AttributePool.LocalVariableTableEntry;
+import com.amd.aparapi.ClassModel.AttributePool.LocalVariableTableEntry.LocalVariableInfo;
+import com.amd.aparapi.InstructionSet.AssignToLocalVariable;
+import com.amd.aparapi.InstructionSet.Branch;
+import com.amd.aparapi.InstructionSet.ByteCode;
+import com.amd.aparapi.InstructionSet.CompositeArbitraryScopeInstruction;
+import com.amd.aparapi.InstructionSet.CompositeInstruction;
+import com.amd.aparapi.InstructionSet.ConditionalBranch;
+import com.amd.aparapi.InstructionSet.FakeGoto;
+import com.amd.aparapi.InstructionSet.Return;
+import com.amd.aparapi.InstructionSet.UnconditionalBranch;
+
+/**
+ * Essentially a glorified linked list of Instructions plus some additional state to allow us to transform sequences.
+ * 
+ * ExpressionLists do have the notion of a parent which allows us to clone an existing parent, allow transformations 
+ * and then possibly commit or abort the transformations at will. 
+ * @author gfrost
+ *
+ */
+class ExpressionList{
+
+   private static Logger logger = Logger.getLogger(Config.getLoggerName());
+
+   private MethodModel methodModel;
+
+   private ExpressionList parent;
+
+   private Instruction head;
+
+   private Instruction tail;
+
+   private Instruction instruction;
+
+   private ExpressionList(MethodModel _methodModel, ExpressionList _parent, Instruction _instruction) {
+
+      methodModel = _methodModel;
+      parent = _parent;
+      instruction = _instruction;
+      if (parent != null) {
+         head = parent.head;
+         tail = parent.tail;
+      }
+      if (instruction != null) {
+         tail = _instruction.getPrevExpr();
+         tail.setNextExpr(null);
+         _instruction.setPrevExpr(null);
+      }
+   }
+
+   ExpressionList(MethodModel _methodModel) {
+      this(_methodModel, null, null);
+   }
+
+   /**
+    * Determine whether the sequence of instructions from _start to _extent is free of branches which extend beyond _extent. 
+    * 
+    * As a side effect, if we find a possible branch it is likely a break or continue so we mark the conditional as such.
+    *
+    * @param _start
+    * @param _extent
+    * @return
+    */
+   boolean doesNotContainContinueOrBreak(Instruction _start, Instruction _extent) {
+      boolean ok = true;
+      boolean breakOrContinue = false;
+      for (Instruction i = _start; i != null; i = i.getNextExpr()) {
+         if (i.isBranch()) {
+            if (i.asBranch().isForwardUnconditional() && i.asBranch().getTarget().isAfter(_extent)) {
+               breakOrContinue = true;
+            } else {
+               ok = false;
+               break;
+            }
+         }
+      }
+      if (ok) {
+         if (breakOrContinue) {
+            for (Instruction i = _start; i != null; i = i.getNextExpr()) {
+               if (i.isBranch() && i.asBranch().isForwardUnconditional() && i.asBranch().getTarget().isAfter(_extent)) {
+                  i.asBranch().setBreakOrContinue(true);
+               }
+            }
+         }
+      }
+      return (ok);
+   }
+
+   boolean doesNotContainCompositeOrBranch(Instruction _start, Instruction _exclusiveEnd) {
+      boolean ok = true;
+      for (Instruction i = _start; i != null && i != _exclusiveEnd; i = i.getNextExpr()) {
+         if (!(i instanceof CompositeInstruction) && (i.isBranch())) {
+            ok = false;
+            break;
+         }
+      }
+      return (ok);
+   }
+
+   void unwind() {
+      if (parent != null) {
+         if (instruction != null) {
+            tail.setNextExpr(instruction);
+            instruction.setPrevExpr(tail);
+            parent.head = head;
+         } else {
+            parent.head = head;
+            parent.tail = tail;
+         }
+      }
+   }
+
+   /**
+    *  [1] [2] [3] [4]
+    *  
+    *  Note that passing null here essentially deletes the existing expression list and returns the expression
+    *  
+    * @param _newTail
+    * @return
+    */
+
+   Instruction createList(final Instruction _newTail) {
+      Instruction childExprHead = null;
+      if (_newTail == null) {
+         childExprHead = head;
+         tail = head = null;
+      } else {
+         childExprHead = _newTail.getNextExpr();
+         tail = _newTail;
+         _newTail.setNextExpr(null);
+         if (childExprHead != null) {
+            childExprHead.setPrevExpr(null);
+         }
+
+      }
+      return (childExprHead);
+   }
+
+   /**
+    * Add this instruction to the end of the list. 
+    * 
+    * @param _instruction
+    * @return The instruction we added
+    */
+
+   Instruction add(Instruction _instruction) {
+
+      if (head == null) {
+         head = _instruction;
+      } else {
+         _instruction.setPrevExpr(tail);
+         tail.setNextExpr(_instruction);
+
+      }
+      tail = _instruction;
+      MethodModel.logger.log(Level.FINE, "After PUSH of " + _instruction + " tail=" + tail);
+      return (tail);
+   }
+
+   /**
+    * Insert the given instruction (_newone) between the existing entries (_prev and _next). 
+    * @param _prev
+    * @param _next
+    * @param _newOne
+    */
+   void insertBetween(Instruction _prev, Instruction _next, Instruction _newOne) {
+      _newOne.setNextExpr(null);
+      _newOne.setPrevExpr(null);
+      if (_prev == null) {
+         // this is the new head
+         if (_next == null) {
+            head = tail = _newOne;
+         } else {
+            _newOne.setNextExpr(head);
+            head.setPrevExpr(_newOne);
+            head = _newOne;
+         }
+      } else if (_next == null) {
+         _newOne.setPrevExpr(tail);
+         tail.setNextExpr(_newOne);
+         tail = _newOne;
+      } else {
+         _newOne.setNextExpr(_prev.getNextExpr());
+         _newOne.setPrevExpr(_next.getPrevExpr());
+         _prev.setNextExpr(_newOne);
+         _next.setPrevExpr(_newOne);
+      }
+
+   }
+
+   /**
+     * Inclusive replace between _head and _tail with _newOne. 
+      * 
+      * <pre>
+      *    |      | --> |       | ---> ... ---> |       | ---> |      |
+      *    | prev |     | _head |               | _tail |      | next |
+      *    |      | <-- |       | <--- ... <----|       | <--- |      |
+      * </pre>
+      *  To 
+      * <pre>
+      *    |      | --> |         | ---> |      |
+      *    | prev |     | _newOne |      | next |
+      *    |      | <-- |         | <--- |      |
+      * </pre>
+      */
+
+   void replaceInclusive(Instruction _head, Instruction _tail, Instruction _newOne) {
+      _newOne.setNextExpr(null);
+      _newOne.setPrevExpr(null);
+      Instruction prevHead = _head.getPrevExpr();
+      if (_tail == null) {
+         // this is the new tail
+         _newOne.setPrevExpr(prevHead);
+         prevHead.setNextExpr(_newOne);
+         tail = _newOne;
+      } else {
+         Instruction tailNext = _tail.getNextExpr();
+         if (prevHead == null) {
+            // this is the new head
+            if (tailNext == null) {
+               head = tail = _newOne;
+            } else {
+               _newOne.setNextExpr(head);
+               head.setPrevExpr(_newOne);
+               head = _newOne;
+            }
+         } else if (tailNext == null) {
+            _newOne.setPrevExpr(prevHead);
+            prevHead.setNextExpr(_newOne);
+            tail = _newOne;
+            _head.setPrevExpr(null);
+         } else {
+            _newOne.setNextExpr(tailNext);
+            _newOne.setPrevExpr(prevHead);
+            prevHead.setNextExpr(_newOne);
+            tailNext.setPrevExpr(_newOne);
+
+         }
+         _tail.setNextExpr(null);
+         _head.setPrevExpr(null);
+      }
+
+   }
+
+   /**
+    * Fold headTail.tail into valid composites
+    * 
+    * <pre>
+    * if(??){then}... 
+    *   ?? ?> [THEN] ...
+    *       -------->
+    *
+    * if (??){THEN}else{ELSE}...
+    * 
+    *   ?? ?> [THEN] >> [ELSE] ...
+    *       ------------>
+    *                 -------->
+    *               
+    * sun for (INIT,??,DELTA){BODY} ...
+    * 
+    *    [INIT] ?? ?> [BODY] [DELTA] << ...
+    *               ------------------>
+    *            <-------------------
+    *        
+    * sun for (,??,DELTA){BODY} ...
+    * 
+    *     ?? ?> [BODY] [DELTA] << ...
+    *         ------------------>
+    *      <-------------------    
+    *        
+    * sun while (?){l} ...
+    * 
+    *    ?? ?> [BODY] << ...
+    *        ----------->
+    *     <------------
+    *               
+    * eclipse for (INIT,??,DELTA){BODY} ...
+    *    [INIT] >> [BODY] [DELTA] ?? ?< ...
+    *            ---------------->
+    *              <-----------------
+    *          
+    * eclipse for (,??,DELTA){BODY} ...
+    *    >> [BODY] [DELTA] ?? ?< ...
+    *     --------------->
+    *       <-----------------
+    *      
+    * eclipse while (??){BODY} ...
+    *    >> [BODY] ?? ?< ...
+    *     -------->
+    *       <----------
+    *
+    * eclipe if (?1) { while (?2) {BODY} } else {ELSE} ...
+    *    ?1 ?> >> [BODY] ?2 ?< >> [ELSE] ...
+    *           --------->
+    *              <---------
+    *        --------------------->    
+    *                           -------->   
+    * 
+    * sun for (,?1,DELTA){ if (?2) { THEN break; } BODY} ...
+    * 
+    *     ?1 ?> ?2 ?> [THEN] >> [BODY] [DELTA] << ...
+    *               ----------->
+    *         ---------------------------------->
+    *                         ------------------>
+    *     <------------------------------------ 
+    *     
+    * sun for (,?1,DELTA){ if (?2) { THEN continue; } BODY} ...
+    * 
+    *     ?1 ?> ?2 ?> THEN >> [BODY] [DELTA] << ...
+    *               --------->
+    *                       -------->
+    *         -------------------------------->
+    *     <----------------------------------     
+    *           
+    * Some exceptions based on sun javac optimizations
+    * 
+    * if (?1){ if (?2){THEN} }else{ ELSE } ...
+    *   One might expect 
+    *    ?1 ?> ?2 ?> [THEN] >> [ELSE] ...
+    *        ----------------->
+    *              -------->!         
+    *                        ------------->
+    *   However the conditional branch to the unconditional (!) is optimized away and instead the unconditional inverted and extended 
+    *                   
+    *    ?1 ?> ?2 ?> [THEN] >> [ELSE] ...
+    *        ----------------->
+    *              --------*--------->
+    *              
+    * sun if (?1) { while (?2) {l} } else {e} ...
+    *   One might expect 
+    *    ?1 ?> ?2 ?> [BODY] << >> [ELSE] ...
+    *        ------------------->
+    *              ----------->!
+    *            <----------    
+    *                           -------->
+    *                    
+    *   However as above the conditional branch to the unconditional (!) can be optimized away and the conditional inverted and extended 
+    *    ?1 ?> ?2 ?> [BODY] << >> [ELSE] ...
+    *        -------------------->
+    *              -----------*--------->   
+    *            <-----------  
+    *              
+    *   However we can also now remove the forward unconditional completely as it is unreachable
+    *    ?1 ?> ?2 ?> [BODY] << [ELSE] ...
+    *        ----------------->
+    *              ------------------>   
+    *            <-----------       
+    *               
+    * sun while(?1){if (?2) {THEN} else {ELSE} } ...
+    *   One might expect 
+    *    ?1 ?> ?2 ?> [BODY] >> [ELSE] << ...
+    *         -------------------------->
+    *           <---------------------
+    *               ---------->    
+    *                         ------->!
+    *                    
+    *   However the unconditional branch to the unconditional backbranch (!) can be optimized away and the unconditional wrapped back directly to the loop control head 
+    *    ?1 ?> ?2 ?> [BODY] << [ELSE] << ...
+    *         -------------------------->
+    *           <---------------------
+    *               ---------->    
+    *           <-----------
+                                        
+    * </pre>
+    * @param _instruction
+    * @throws ClassParseException 
+    */
+   boolean foldComposite(final Instruction _instruction) throws ClassParseException {
+      boolean handled = false;
+      try {
+
+         if (logger.isLoggable(Level.FINE)) {
+            System.out.println("foldComposite: curr = " + _instruction);
+            System.out.println(dumpDiagram(_instruction));
+            // System.out.println(dumpDiagram(null, _instruction));
+         }
+         if (_instruction.isForwardBranchTarget() || (tail != null && tail.isBranch() && tail.asBranch().isReverseConditional())) {
+            while (_instruction.isForwardBranchTarget()
+                  || (tail != null && tail.isBranch() && tail.asBranch().isReverseConditional())) {
+               if (logger.isLoggable(Level.FINE)) {
+                  System.out.println(dumpDiagram(_instruction));
+
+               }
+               handled = false;
+
+               if (tail != null && tail.isBranch() && tail.asBranch().isReverseConditional()) {
+                  /**
+                   * This looks like an eclipse style for/while loop
+                   * <pre>
+                   * eclipse for (INIT,??,DELTA){BODY} ...
+                   *    [INIT] >> [BODY] [DELTA] ?? ?< ...
+                   *            ---------------->
+                   *              <-----------------
+                   *          
+                   * eclipse for (,??,DELTA){BODY} ...
+                   *    >> [BODY] [DELTA] ?? ?< ...
+                   *     --------------->
+                   *       <-----------------
+                   *      
+                   * eclipse while (??){BODY} ...
+                   *    >> [BODY] ?? ?< ...
+                   *     -------->
+                   *       <----------
+                   * </pre>
+                   **/
+                  BranchSet branchSet = ((ConditionalBranch) tail.asBranch()).getOrCreateBranchSet();
+                  Instruction loopTop = branchSet.getTarget().getRootExpr();
+                  Instruction beginingOfBranch = branchSet.getFirst();
+
+                  Instruction startOfBeginningOfBranch = beginingOfBranch.getStartInstruction();
+                  // empty loops sometimes look like eclipse loops!
+                  if (startOfBeginningOfBranch == loopTop) {
+
+                     loopTop = loopTop.getPrevExpr();
+                     if (loopTop instanceof AssignToLocalVariable) {
+                        LocalVariableInfo localVariableInfo = ((AssignToLocalVariable) loopTop).getLocalVariableInfo();
+                        if (localVariableInfo.getStart() == loopTop.getNextExpr().getStartPC()
+                              && localVariableInfo.getEnd() == _instruction.getThisPC()) {
+                           loopTop = loopTop.getPrevExpr(); // back up over the initialization
+                        }
+                     }
+                     addAsComposites(ByteCode.COMPOSITE_EMPTY_LOOP, loopTop, branchSet);
+                     handled = true;
+                  } else {
+
+                     if (loopTop.getPrevExpr() != null && loopTop.getPrevExpr().isBranch()
+                           && loopTop.getPrevExpr().asBranch().isForwardUnconditional()) {
+                        if (doesNotContainCompositeOrBranch(branchSet.getTarget().getRootExpr(), branchSet.getFirst().getPrevExpr())) {
+                           branchSet.unhook();
+                           loopTop.getPrevExpr().asBranch().unhook();
+                           loopTop = loopTop.getPrevExpr();
+                           // looptop == the unconditional?
+                           loopTop = loopTop.getPrevExpr();
+                           if (loopTop instanceof AssignToLocalVariable) {
+                              LocalVariableInfo localVariableInfo = ((AssignToLocalVariable) loopTop).getLocalVariableInfo();
+                              if (localVariableInfo.getStart() == loopTop.getNextExpr().getStartPC()
+                                    && localVariableInfo.getEnd() == _instruction.getThisPC()) {
+                                 loopTop = loopTop.getPrevExpr(); // back up over the initialization
+                              }
+                           }
+                           addAsComposites(ByteCode.COMPOSITE_FOR_ECLIPSE, loopTop, branchSet);
+                           handled = true;
+                        }
+                     }
+                  }
+               }
+               if (!handled && _instruction.isForwardConditionalBranchTarget() && tail.isBranch()
+                     && tail.asBranch().isReverseUnconditional()) {
+
+                  /**
+                   * This is s sun style loop 
+                   * <pre>       
+                   * sun for (INIT,??,DELTA){BODY} ...
+                   * 
+                   *    [INIT] ?? ?> [BODY] [DELTA] << ...
+                   *               ------------------>
+                   *            <-------------------
+                   *        
+                   * sun for (,??,DELTA){BODY} ...
+                   * 
+                   *     ?? ?> [BODY] [DELTA] << ...
+                   *         ------------------>
+                   *      <-------------------    
+                   *        
+                   * sun while (?){l} ...
+                   *  
+                   *    ?? ?> [BODY] << ...
+                   *         ----------->
+                   *     <------------
+                   *               
+                   *</pre>
+                   */
+                  ConditionalBranch lastForwardConditional = _instruction.getForwardConditionalBranches().getLast();
+                  BranchSet branchSet = lastForwardConditional.getOrCreateBranchSet();
+                  Branch reverseGoto = tail.asBranch();
+                  Instruction loopBackTarget = reverseGoto.getTarget();
+                  if (loopBackTarget.getReverseUnconditionalBranches().size() > 1) {
+                     throw new ClassParseException(ClassParseException.TYPE.CONFUSINGBRANCHESPOSSIBLYCONTINUE);
+                  }
+                  if (_instruction.isForwardUnconditionalBranchTarget()) {
+                     /**
+                      * Check if we have a break
+                      * <pre>              
+                      *    ?? ?> [BODY] ?1 ?> >> [BODY] << ...
+                      *         -------------------------->
+                      *                     ---->
+                      *                        ----------->
+                      *     <----------------------------
+                      *               
+                      *</pre>
+                      */
+                     Branch lastForwardUnconditional = _instruction.getForwardUnconditionalBranches().getLast();
+                     if (lastForwardUnconditional != null && lastForwardUnconditional.isAfter(lastForwardConditional)) {
+                        throw new ClassParseException(ClassParseException.TYPE.CONFUSINGBRANCHESPOSSIBLYBREAK);
+                     }
+                  }
+                  if (loopBackTarget != branchSet.getFirst().getStartInstruction()) {
+                     /**
+                      * we may have a if(?1){while(?2){}}else{...} where the else goto has been optimized away. 
+                      * <pre>
+                      *   One might expect 
+                      *    ?1 ?> ?2 ?> [BODY] << >> [ELSE] ...
+                      *        ------------------->
+                      *              ----------->!
+                      *            <----------    
+                      *                           -------->
+                      *                    
+                      *   However as above the conditional branch to the unconditional (!) can be optimized away and the conditional inverted and extended 
+                      *    ?1 ?> ?2 ?> [BODY] << >> [ELSE] ...
+                      *        -------------------->
+                      *              -----------*--------->   
+                      *            <-----------  
+                      *              
+                      *   However we can also now remove the forward unconditional completely as it is unreachable
+                      *    ?1 ?> ?2 ?> [BODY] << [ELSE] ...
+                      *        ----------------->
+                      *              ------------------>   
+                      *            <-----------       
+                      *               
+                      * </pre>
+                      */
+
+                     Instruction loopbackTargetRoot = loopBackTarget.getRootExpr();
+                     if (loopbackTargetRoot.isBranch() && loopbackTargetRoot.asBranch().isConditional()) {
+                        ConditionalBranch topOfRealLoop = (ConditionalBranch) loopbackTargetRoot.asBranch();
+                        BranchSet extentBranchSet = topOfRealLoop.getBranchSet();
+                        if (topOfRealLoop.getBranchSet() == null) {
+                           extentBranchSet = topOfRealLoop.findEndOfConditionalBranchSet(_instruction.getNextPC())
+                                 .getOrCreateBranchSet();
+                        }
+                        // We believe that this extendBranchSet is the real top of the while.
+                        if (doesNotContainCompositeOrBranch(extentBranchSet.getLast().getNextExpr(), reverseGoto)) {
+
+                           Instruction loopTop = topOfRealLoop.getPrevExpr();
+                           if (loopTop instanceof AssignToLocalVariable) {
+                              LocalVariableInfo localVariableInfo = ((AssignToLocalVariable) loopTop).getLocalVariableInfo();
+                              if (localVariableInfo.getStart() == loopTop.getNextExpr().getStartPC()
+                                    && localVariableInfo.getEnd() == _instruction.getThisPC()) {
+                                 loopTop = loopTop.getPrevExpr(); // back up over the initialization
+                              }
+                           }
+                           extentBranchSet.unhook();
+
+                           addAsComposites(ByteCode.COMPOSITE_FOR_SUN, loopTop, extentBranchSet);
+                           UnconditionalBranch fakeGoto = new FakeGoto(methodModel, extentBranchSet.getLast().getTarget());
+
+                           add(fakeGoto);
+                           extentBranchSet.getLast().getTarget().addBranchTarget(fakeGoto);
+
+                           handled = true;
+                        }
+                     }
+                  } else {
+                     /**
+                      * Just a normal sun style loop
+                      */
+                     if (doesNotContainCompositeOrBranch(branchSet.getLast().getNextExpr(), reverseGoto)) {
+                        Instruction loopTop = reverseGoto.getTarget().getRootExpr().getPrevExpr();
+
+                        if (logger.isLoggable(Level.FINEST)) {
+                           Instruction next = branchSet.getFirst().getNextExpr();
+                           System.out.println("### for/while candidate exprs: " + branchSet.getFirst());
+                           while (next != null) {
+                              System.out.println("### expr = " + next);
+                              next = next.getNextExpr();
+                           }
+                        }
+
+                        if (loopTop instanceof AssignToLocalVariable) {
+                           LocalVariableInfo localVariableInfo = ((AssignToLocalVariable) loopTop).getLocalVariableInfo();
+                           if (localVariableInfo.getStart() == loopTop.getNextExpr().getStartPC()
+                                 && localVariableInfo.getEnd() == _instruction.getThisPC()) {
+                              loopTop = loopTop.getPrevExpr(); // back up over the initialization
+
+                           }
+                        }
+                        branchSet.unhook();
+
+                        // If there is an inner scope, it is likely that the loop counter var
+                        // is modified using an inner scope variable so use while rather than for
+                        if (reverseGoto.getPrevExpr() instanceof CompositeArbitraryScopeInstruction) {
+                           addAsComposites(ByteCode.COMPOSITE_WHILE, loopTop, branchSet);
+                        } else {
+                           addAsComposites(ByteCode.COMPOSITE_FOR_SUN, loopTop, branchSet);
+                        }
+                        handled = true;
+                     }
+
+                  }
+               }
+               if (!handled && !tail.isForwardBranch() && _instruction.isForwardConditionalBranchTarget()) {
+                  /**
+                   * This an if(exp) 
+                   *<pre>             *
+                   * if(??){then}... 
+                   *   ?? ?> [THEN] ...
+                   *       -------->
+                   *
+                   *</pre>
+                   */
+                  ConditionalBranch lastForwardConditional = _instruction.getForwardConditionalBranches().getLast();
+                  BranchSet branchSet = lastForwardConditional.getOrCreateBranchSet();
+                  if (doesNotContainContinueOrBreak(branchSet.getLast().getNextExpr(), _instruction)) {
+                     branchSet.unhook();
+                     addAsComposites(ByteCode.COMPOSITE_IF, branchSet.getFirst().getPrevExpr(), branchSet);
+                     handled = true;
+                  }
+               }
+               if (!handled && !tail.isForwardBranch() && _instruction.isForwardUnconditionalBranchTarget()) {
+
+                  LinkedList<Branch> forwardUnconditionalBranches = _instruction.getForwardUnconditionalBranches();
+
+                  Branch lastForwardUnconditional = forwardUnconditionalBranches.getLast();
+                  Instruction afterGoto = lastForwardUnconditional.getNextExpr();
+                  if (afterGoto.getStartInstruction().isForwardConditionalBranchTarget()) {
+                     LinkedList<ConditionalBranch> forwardConditionalBranches = afterGoto.getStartInstruction()
+                           .getForwardConditionalBranches();
+                     ConditionalBranch lastForwardConditional = forwardConditionalBranches.getLast();
+                     BranchSet branchSet = lastForwardConditional.getOrCreateBranchSet();
+
+                     if (doesNotContainCompositeOrBranch(branchSet.getLast().getNextExpr(), lastForwardUnconditional)) {
+                        if (doesNotContainContinueOrBreak(afterGoto.getNextExpr(), _instruction)) {
+                           branchSet.unhook();
+                           lastForwardUnconditional.unhook();
+                           addAsComposites(ByteCode.COMPOSITE_IF_ELSE, branchSet.getFirst().getPrevExpr(), branchSet);
+                           handled = true;
+                        }
+                     } else {
+                        //then not clean.   
+                        ExpressionList newHeadTail = new ExpressionList(methodModel, this, lastForwardUnconditional);
+                        handled = newHeadTail.foldComposite(lastForwardUnconditional.getStartInstruction());
+                        newHeadTail.unwind();
+                        // handled = foldCompositeRecurse(lastForwardUnconditional);
+                        if (!handled && forwardUnconditionalBranches.size() > 1) {
+                           //  BI  AI      AE      BE
+                           //  ?>  ?>  ..  >>  ..  >>   C   S  
+                           //  ?---------------------->22    
+                           //      ?---------->18            
+                           //              +-------------->31
+                           //                      +------>31
+                           // Javac sometimes performs the above optimization.  Basically the GOTO for the inner IFELSE(AI,AE) instead of targeting the GOTO
+                           // from the outer IFELSE(B1,BE) so instead of AE->BE->... we have AE-->...
+                           //
+                           // So given more than one target we retreat up the list of unconditionals until we find a clean one treating the previously visited GOTO 
+                           // as a possible end
+
+                           for (int i = forwardUnconditionalBranches.size(); i > 1; i--) {
+                              Branch thisGoto = forwardUnconditionalBranches.get(i - 1);
+                              Branch elseGoto = forwardUnconditionalBranches.get(i - 2);
+                              Instruction afterElseGoto = elseGoto.getNextExpr();
+                              if (afterElseGoto.getStartInstruction().isConditionalBranchTarget()) {
+                                 BranchSet elseBranchSet = afterElseGoto.getStartInstruction().getForwardConditionalBranches()
+                                       .getLast().getOrCreateBranchSet();
+                                 if (doesNotContainCompositeOrBranch(elseBranchSet.getLast().getNextExpr(), elseGoto)) {
+                                    if (doesNotContainCompositeOrBranch(afterElseGoto.getNextExpr(), thisGoto)) {
+                                       if (logger.isLoggable(Level.FINE)) {
+                                          System.out.println(dumpDiagram(_instruction));
+                                       }
+                                       elseBranchSet.unhook();
+                                       elseGoto.unhook();
+                                       if (logger.isLoggable(Level.FINE)) {
+                                          System.out.println(dumpDiagram(_instruction));
+
+                                       }
+
+                                       CompositeInstruction composite = CompositeInstruction.create(ByteCode.COMPOSITE_IF_ELSE,
+                                             methodModel, elseBranchSet.getFirst(), thisGoto, elseBranchSet);
+                                       replaceInclusive(elseBranchSet.getFirst(), thisGoto.getPrevExpr(), composite);
+
+                                       handled = true;
+
+                                       break;
+                                    }
+                                 }
+                              }
+
+                           }
+
+                        }
+                     }
+
+                  }
+
+               }
+               if (!handled && !tail.isForwardBranch() && _instruction.isForwardConditionalBranchTarget()
+                     && _instruction.isForwardUnconditionalBranchTarget()) {
+                  // here we have multiple composites ending at the same point
+
+                  Branch lastForwardUnconditional = _instruction.getForwardUnconditionalBranches().getLast();
+                  ConditionalBranch lastForwardConditional = _instruction.getStartInstruction().getForwardConditionalBranches()
+                        .getLast();
+                  // we will clip the tail and see if recursing helps
+
+                  if (lastForwardConditional.getTarget().isAfter(lastForwardUnconditional)) {
+
+                     lastForwardConditional.retarget(lastForwardUnconditional);
+
+                     ExpressionList newHeadTail = new ExpressionList(methodModel, this, lastForwardUnconditional);
+                     handled = newHeadTail.foldComposite(lastForwardUnconditional.getStartInstruction());
+                     newHeadTail.unwind();
+
+                  }
+
+               }
+               if (!handled) {
+                  break;
+               }
+            }
+
+         } else {
+
+            // might be end of arbitrary scope
+            LocalVariableTableEntry localVariableTable = methodModel.getMethod().getLocalVariableTableEntry();
+            int startPc = Short.MAX_VALUE;
+            for (LocalVariableInfo localVariableInfo : localVariableTable.getPool()) {
+
+               if (localVariableInfo.getEnd() == _instruction.getThisPC()) {
+                  logger.fine(localVariableInfo.getVariableName() + "  scope  " + localVariableInfo.getStart() + " ,"
+                        + localVariableInfo.getEnd());
+                  if (localVariableInfo.getStart() < startPc) {
+                     startPc = localVariableInfo.getStart();
+                  }
+               }
+
+            }
+            if (startPc < Short.MAX_VALUE) {
+               logger.fine("Scope block from " + startPc + " to  " + (tail.getThisPC() + tail.getLength()));
+               for (Instruction i = head; i != null; i = i.getNextPC()) {
+                  if (i.getThisPC() == startPc) {
+                     Instruction startInstruction = i.getRootExpr().getPrevExpr();
+                     logger.fine("Start = " + startInstruction);
+
+                     addAsComposites(ByteCode.COMPOSITE_ARBITRARY_SCOPE, startInstruction.getPrevExpr(), null);
+                     handled = true;
+                     break;
+                  }
+               }
+
+            }
+
+         }
+
+         if (Config.instructionListener != null) {
+            Config.instructionListener.showAndTell("after folding", head, _instruction);
+         }
+
+      } catch (ClassParseException _classParseException) {
+         throw new ClassParseException(_classParseException);
+      } catch (Throwable t) {
+         throw new ClassParseException(t);
+
+      }
+      return (handled);
+   }
+
+   private void addAsComposites(ByteCode _byteCode, Instruction _start, BranchSet _branchSet) {
+      Instruction childTail = tail;
+      Instruction childHead = createList(_start);
+      CompositeInstruction composite = CompositeInstruction.create(_byteCode, methodModel, childHead, childTail, _branchSet);
+      add(composite);
+   }
+
+   /**
+    * Aids debugging.  Creates a diagrammatic form of the roots (+ tail instruction) so that we can analyze control flow. 
+    * <pre>
+    * I I I C C I U I U[I]I
+    *       |---------->1
+    *         |---->1
+    *             |------>2
+    *                 |-->2
+    * </pre>
+    * @param _cursor The instruction we are looking at
+    * @param _instruction The instruction we are considering adding (may be null)
+    * @return
+    */
+   String dumpDiagram(Instruction _instruction) {
+      StringBuilder sb = new StringBuilder();
+      List<Instruction> list = new ArrayList<Instruction>();
+
+      for (Instruction i = head; i != null; i = i.getNextExpr()) {
+         list.add(i);
+      }
+
+      for (Instruction i = _instruction; i != null; i = i.getNextPC()) {
+         list.add(i);
+      }
+      Instruction[] array = list.toArray(new Instruction[0]);
+      boolean lastWasCursor = false;
+
+      List<Branch> branches = new ArrayList<Branch>();
+      for (Instruction i : list) {
+         sb.append(String.format(" %3d", i.getStartPC()));
+      }
+      sb.append("\n");
+      for (Instruction i : list) {
+         sb.append(String.format(" %3d", i.getThisPC()));
+      }
+      sb.append("\n");
+      for (Instruction i : list) {
+
+         if (i == _instruction) {
+            sb.append(" [");
+            lastWasCursor = true;
+         } else {
+            if (lastWasCursor) {
+               sb.append("] ");
+               lastWasCursor = false;
+            } else {
+               sb.append("  ");
+            }
+         }
+         if (i.isBranch() && i.asBranch().isConditional()) {
+            branches.add(i.asBranch());
+
+            if (i.asBranch().isForward()) {
+               sb.append("?>");
+
+            } else {
+               sb.append("?<");
+            }
+         } else if (i.isBranch() && i.asBranch().isUnconditional()) {
+            branches.add(i.asBranch());
+            if (i.asBranch().isForward()) {
+               sb.append(">>");
+            } else {
+               sb.append("<<");
+            }
+         } else if (i instanceof CompositeInstruction) {
+            sb.append(" C");
+         } else if (i instanceof Return) {
+
+            sb.append(" R");
+            // } else if (i instanceof AssignToLocalVariable) {
+            //    sb.append(" S");
+         } else {
+            sb.append("..");
+         }
+      }
+      if (lastWasCursor) {
+         sb.append("] ");
+      } else {
+         sb.append("  ");
+      }
+      for (Branch b : branches) {
+         sb.append("\n   ");
+         if (b.isForward()) {
+            for (int i = 0; i < array.length; i++) {
+               if (array[i].getStartPC() < b.getStartPC() || array[i].getThisPC() > b.getTarget().getThisPC()) {
+                  sb.append("    ");
+               } else {
+                  if (b.isConditional()) {
+                     sb.append("?-");
+                  } else {
+                     sb.append("+-");
+                  }
+                  i++;
+                  while (i < array.length && array[i].getStartPC() < b.getTarget().getThisPC()) {
+                     sb.append("----");
+                     i++;
+                  }
+                  sb.append("->");
+                  sb.append(b.getTarget().getThisPC());
+
+               }
+            }
+         } else {
+            for (int i = 0; i < array.length; i++) {
+               if (array[i].getStartPC() < b.getTarget().getThisPC() || array[i].getThisPC() > b.getThisPC()) {
+                  sb.append("    ");
+               } else {
+                  sb.append("<-");
+                  i++;
+                  while (i < array.length && array[i].getStartPC() < b.getThisPC()) {
+                     sb.append("----");
+                     i++;
+                  }
+                  if (b.isConditional()) {
+                     sb.append("-?");
+                  } else {
+                     sb.append("-+");
+                  }
+               }
+            }
+         }
+      }
+
+      return (sb.toString());
+   }
+
+   Instruction getTail() {
+      return (tail);
+   }
+
+   Instruction getHead() {
+      return (head);
+   }
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/Instruction.java b/com.amd.aparapi/src/java/com/amd/aparapi/Instruction.java
new file mode 100644
index 00000000..a2f0668c
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/Instruction.java
@@ -0,0 +1,388 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.util.LinkedList;
+
+import com.amd.aparapi.InstructionSet.Branch;
+import com.amd.aparapi.InstructionSet.ByteCode;
+import com.amd.aparapi.InstructionSet.CompositeInstruction;
+import com.amd.aparapi.InstructionSet.ConditionalBranch;
+
+/**
+ * Initially represents a single Java bytecode instruction.
+ * 
+ * Instructions for each bytecode are created when the bytecode is first scanned.  
+ * 
+ * Each Instruction will contain a pc (program counter) offset from the beginning of the sequence of bytecode and the length will be determined by the information gleaned from InstructionSet.BYTECODE.
+ * 
+ * 
+ * @author gfrost
+ *
+ */
+abstract class Instruction{
+
+   protected MethodModel method;
+
+   private ByteCode byteCode;
+
+   private int length;
+
+   protected int pc;
+
+   abstract String getDescription();
+
+   private Instruction nextPC = null;
+
+   private Instruction prevPC = null;
+
+   private Instruction nextExpr = null;
+
+   private Instruction prevExpr = null;
+
+   private Instruction parentExpr = null;
+
+   private LinkedList<ConditionalBranch> forwardConditionalBranchTargets;
+
+   private LinkedList<ConditionalBranch> reverseConditionalBranchTargets;
+
+   private LinkedList<Branch> forwardUnconditionalBranchTargets;
+
+   private LinkedList<Branch> reverseUnconditionalBranchTargets;
+
+   private Instruction firstChild = null;
+
+   private Instruction lastChild = null;
+
+   protected void setChildren(Instruction _firstChild, Instruction _lastChild) {
+
+      if (_firstChild == null || _lastChild == null) {
+         throw new IllegalStateException("null children added");
+      }
+      firstChild = _firstChild;
+      lastChild = _lastChild;
+
+      for (Instruction i = firstChild; i != lastChild; i = i.getNextExpr()) {
+         if (i == null) {
+            throw new IllegalStateException("child list broken ");
+         }
+         i.setParentExpr(this);
+      }
+      lastChild.setParentExpr(this);
+   }
+
+   Instruction getPrevExpr() {
+      return (prevExpr);
+
+   }
+
+   Instruction getNextExpr() {
+      return (nextExpr);
+   }
+
+   void setNextPC(Instruction _nextByPC) {
+      nextPC = _nextByPC;
+   }
+
+   void setPrevPC(Instruction _prevByPC) {
+      prevPC = _prevByPC;
+   }
+
+   void setPrevExpr(Instruction _prevExpr) {
+      prevExpr = _prevExpr;
+   }
+
+   void setNextExpr(Instruction _nextExpr) {
+      nextExpr = _nextExpr;
+   }
+
+   Instruction toInstruction() {
+      return (this);
+   }
+
+   final int getLength() {
+      return (length);
+   }
+
+   final void setLength(int _length) {
+      length = _length;
+   }
+
+   final ByteCode getByteCode() {
+      return (byteCode);
+   }
+
+   int getThisPC() {
+      return (pc);
+   }
+
+   int getStartPC() {
+      return (getFirstChild() == null ? pc : getFirstChild().getStartPC());
+   }
+
+   protected Instruction(MethodModel _method, ByteCode _byteCode, int _pc) {
+      method = _method;
+      pc = _pc;
+      byteCode = _byteCode;
+   }
+
+   protected Instruction(MethodModel _method, ByteCode _byteCode, ByteReader _byteReader) {
+      this(_method, _byteCode, _byteReader.getOffset() - 1);
+   }
+
+   // This works for most cases (except calls whose operand count depends upon the signature) so all call instructions therefore override this method
+   int getStackConsumeCount() {
+      return (byteCode.getPop().getStackAdjust());
+   }
+
+   int getStackProduceCount() {
+      return (byteCode.getPush().getStackAdjust());
+   }
+
+   int getStackDelta() {
+      return (getStackProduceCount() - getStackConsumeCount());
+   }
+
+   @Override public String toString() {
+      return (String.format("%d %s", pc, byteCode.getName()));
+   }
+
+   boolean isBranch() {
+      return (this instanceof Branch);
+   }
+
+   int compareTo(Instruction _other) {
+      return (pc - _other.pc);
+   }
+
+   boolean isAfter(Instruction _other) {
+      return (compareTo(_other) > 0);
+   }
+
+   boolean isAfterOrEqual(Instruction _other) {
+      return (compareTo(_other) >= 0);
+   }
+
+   boolean isBefore(Instruction _other) {
+      return (compareTo(_other) < 0);
+   }
+
+   boolean isBeforeOrEqual(Instruction _other) {
+      return (compareTo(_other) <= 0);
+   }
+
+   Instruction getFirstChild() {
+      return (firstChild);
+   }
+
+   Instruction getLastChild() {
+      return (lastChild);
+   }
+
+   Instruction getStartInstruction() {
+      return (getFirstChild() == null ? this : getFirstChild().getStartInstruction());
+
+   }
+
+   MethodModel getMethod() {
+      return (method);
+   }
+
+   Instruction getNextPC() {
+      return (nextPC);
+   }
+
+   Instruction getPrevPC() {
+      return (prevPC);
+   }
+
+   void setParentExpr(Instruction _parentExpr) {
+      parentExpr = _parentExpr;
+   }
+
+   Instruction getParentExpr() {
+      return (parentExpr);
+   }
+
+   Instruction getRootExpr() {
+      return (parentExpr == null ? this : parentExpr.getRootExpr());
+   }
+
+   boolean isReverseConditionalBranchTarget() {
+      return (reverseConditionalBranchTargets != null && reverseConditionalBranchTargets.size() > 0);
+   }
+
+   boolean isForwardConditionalBranchTarget() {
+      return (forwardConditionalBranchTargets != null && forwardConditionalBranchTargets.size() > 0);
+   }
+
+   boolean isReverseUnconditionalBranchTarget() {
+      return (reverseUnconditionalBranchTargets != null && reverseUnconditionalBranchTargets.size() > 0);
+   }
+
+   boolean isForwardUnconditionalBranchTarget() {
+      return (forwardUnconditionalBranchTargets != null && forwardUnconditionalBranchTargets.size() > 0);
+   }
+
+   boolean isReverseBranchTarget() {
+      return (isReverseConditionalBranchTarget() || isReverseUnconditionalBranchTarget());
+   }
+
+   boolean isConditionalBranchTarget() {
+      return (isReverseConditionalBranchTarget() || isForwardConditionalBranchTarget());
+   }
+
+   boolean isUnconditionalBranchTarget() {
+      return (isReverseUnconditionalBranchTarget() || isForwardUnconditionalBranchTarget());
+   }
+
+   boolean isForwardBranchTarget() {
+      return (isForwardConditionalBranchTarget() || isForwardUnconditionalBranchTarget());
+   }
+
+   boolean isBranchTarget() {
+      return (isForwardBranchTarget() || isReverseBranchTarget());
+   }
+
+   boolean producesStack() {
+      return (this instanceof CompositeInstruction || (getStackProduceCount() > 0));
+   }
+
+   Instruction getReal() {
+      return (this);
+   }
+
+   Branch asBranch() {
+      return ((Branch) this);
+   }
+
+   boolean consumesStack() {
+      return (getStackConsumeCount() > 0);
+   }
+
+   void addBranchTarget(Branch _branch) {
+
+      if (_branch.isReverse()) {
+         if (_branch.isConditional()) {
+            if (reverseConditionalBranchTargets == null) {
+               reverseConditionalBranchTargets = new LinkedList<ConditionalBranch>();
+            }
+            reverseConditionalBranchTargets.add((ConditionalBranch) _branch);
+         } else {
+            if (reverseUnconditionalBranchTargets == null) {
+               reverseUnconditionalBranchTargets = new LinkedList<Branch>();
+            }
+            reverseUnconditionalBranchTargets.add(_branch);
+         }
+      } else {
+         if (_branch.isConditional()) {
+            if (forwardConditionalBranchTargets == null) {
+               forwardConditionalBranchTargets = new LinkedList<ConditionalBranch>();
+            }
+            forwardConditionalBranchTargets.add((ConditionalBranch) _branch);
+         } else {
+            if (forwardUnconditionalBranchTargets == null) {
+               forwardUnconditionalBranchTargets = new LinkedList<Branch>();
+            }
+            forwardUnconditionalBranchTargets.add(_branch);
+         }
+      }
+
+   }
+
+   void removeBranchTarget(Branch _branch) {
+      if (_branch.isReverse()) {
+         if (_branch.isConditional()) {
+            if (reverseConditionalBranchTargets != null) {
+               reverseConditionalBranchTargets.remove(_branch);
+               if (reverseConditionalBranchTargets.size() == 0) {
+                  reverseConditionalBranchTargets = null;
+               }
+            }
+         } else {
+            if (reverseUnconditionalBranchTargets != null) {
+               reverseUnconditionalBranchTargets.remove(_branch);
+               if (reverseUnconditionalBranchTargets.size() == 0) {
+                  reverseUnconditionalBranchTargets = null;
+               }
+            }
+         }
+      } else {
+         if (_branch.isConditional()) {
+            if (forwardConditionalBranchTargets != null) {
+               forwardConditionalBranchTargets.remove(_branch);
+               if (forwardConditionalBranchTargets.size() == 0) {
+                  forwardConditionalBranchTargets = null;
+               }
+            }
+         } else {
+            if (forwardUnconditionalBranchTargets != null) {
+               forwardUnconditionalBranchTargets.remove(_branch);
+               if (forwardUnconditionalBranchTargets.size() == 0) {
+                  forwardUnconditionalBranchTargets = null;
+               }
+            }
+         }
+      }
+   }
+
+   LinkedList<Branch> getForwardUnconditionalBranches() {
+      return (forwardUnconditionalBranchTargets);
+   }
+
+   LinkedList<ConditionalBranch> getForwardConditionalBranches() {
+      return (forwardConditionalBranchTargets);
+   }
+
+   LinkedList<Branch> getReverseUnconditionalBranches() {
+      return (reverseUnconditionalBranchTargets);
+   }
+
+   LinkedList<ConditionalBranch> getReverseConditionalBranches() {
+      return (reverseConditionalBranchTargets);
+   }
+
+   boolean isForwardBranch() {
+      return (isBranch() && asBranch().isForward());
+   }
+
+   boolean sameAs(Instruction _other) {
+      return (equals(_other));
+   }
+
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/InstructionPattern.java b/com.amd.aparapi/src/java/com/amd/aparapi/InstructionPattern.java
new file mode 100644
index 00000000..9462fc08
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/InstructionPattern.java
@@ -0,0 +1,507 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import com.amd.aparapi.InstructionSet.AccessArrayElement;
+import com.amd.aparapi.InstructionSet.AccessInstanceField;
+import com.amd.aparapi.InstructionSet.AccessLocalVariable;
+import com.amd.aparapi.InstructionSet.AssignToArrayElement;
+import com.amd.aparapi.InstructionSet.AssignToInstanceField;
+import com.amd.aparapi.InstructionSet.AssignToLocalVariable;
+import com.amd.aparapi.InstructionSet.CastOperator;
+import com.amd.aparapi.InstructionSet.Constant;
+import com.amd.aparapi.InstructionSet.I_IADD;
+import com.amd.aparapi.InstructionSet.I_ICONST_1;
+import com.amd.aparapi.InstructionSet.I_IINC;
+import com.amd.aparapi.InstructionSet.I_ISUB;
+import com.amd.aparapi.InstructionSet.MethodCall;
+
+class InstructionPattern{
+
+   @SuppressWarnings("unused") private boolean compareSubTrees(Instruction _lhs, Instruction _rhs) {
+      _lhs = _lhs.getReal();
+      _rhs = _rhs.getReal();
+      boolean same = _lhs.sameAs(_rhs);
+      if (same) {
+         Instruction lhsChild = _lhs.getFirstChild();
+         Instruction rhsChild = _rhs.getFirstChild();
+         while (same && lhsChild != null && rhsChild != null) {
+            same = same && compareSubTrees(lhsChild, rhsChild);
+            if (same) {
+               rhsChild = rhsChild.getNextExpr();
+               lhsChild = lhsChild.getNextExpr();
+            }
+         }
+         same = same && lhsChild == rhsChild;
+
+      }
+      return (same);
+   }
+
+   static class InstructionMatch{
+      final boolean ok;
+
+      static final InstructionMatch TRUE = new InstructionMatch(true);
+
+      static final InstructionMatch FALSE = new InstructionMatch(false);
+
+      InstructionMatch(boolean _ok) {
+         ok = _ok;
+      }
+
+      static InstructionMatch test(boolean _condition) {
+         return (_condition ? TRUE : FALSE);
+      }
+
+   }
+
+   static abstract class InstructionMatcher{
+
+      private String description;
+
+      abstract InstructionMatch matches(Instruction _instruction);
+
+      InstructionMatch matches(Instruction _instruction, InstructionMatcher _instructionMatcher) {
+         if (matches(_instruction.getReal()).ok) {
+            if (_instruction.getNextExpr() != null) {
+               return (_instructionMatcher.matches(_instruction.getNextExpr().getReal()));
+            }
+         }
+         return (InstructionMatch.FALSE);
+      }
+
+      InstructionMatcher(String _description) {
+         description = _description;
+      }
+
+      String getDescription() {
+         return (description);
+      }
+   }
+
+   class AssignableInstructionMatcher extends InstructionMatcher{
+      private Class<?>[] classes;
+
+      AssignableInstructionMatcher(Class<?>... _classes) {
+         super("AssignableInstructionMatcher");
+         classes = _classes;
+      }
+
+      @Override InstructionMatch matches(Instruction _instruction) {
+
+         for (Class<?> c : classes) {
+            if (c.isAssignableFrom(_instruction.getClass())) {
+               return (InstructionMatch.TRUE);
+
+            }
+         }
+         return (InstructionMatch.TRUE);
+      }
+   }
+
+   static final InstructionMatcher assignToLocalVariable = new InstructionMatcher("Assign to local variable"){
+
+      @Override InstructionMatch matches(Instruction _instruction) {
+         return (InstructionMatch.test(_instruction instanceof AssignToLocalVariable));
+      }
+
+   };
+
+   static final InstructionMatcher constant = new InstructionMatcher("Constant "){
+
+      @Override InstructionMatch matches(Instruction _instruction) {
+         return (InstructionMatch.test(_instruction instanceof Constant<?>));
+      }
+
+   };
+
+   static final InstructionMatcher assignToArrayElement = new InstructionMatcher("Assign to array element"){
+
+      @Override InstructionMatch matches(Instruction _instruction) {
+         return (InstructionMatch.test(_instruction instanceof AssignToArrayElement));
+      }
+
+   };
+
+   static final InstructionMatcher methodCall = new InstructionMatcher("Method Call"){
+
+      @Override InstructionMatch matches(Instruction _instruction) {
+
+         return (InstructionMatch.test(_instruction instanceof MethodCall));
+      }
+
+   };
+
+   static final InstructionMatcher longHandIncLocalVariable = new InstructionMatcher("Long hand increment of local variable"){
+      /**
+       * <pre>
+       *                                                   
+       *                  / iload<n>         
+       *  istore<n> - iadd                       
+       *                  \ i_const_1   
+       *                  
+       *                          / iload<n>         
+       *  istore<n> - (?2i) - iadd                       
+       *                          \ i_const_1    
+       *
+       * </pre>
+       */
+      @Override InstructionMatch matches(Instruction _instruction) {
+         if (_instruction instanceof AssignToLocalVariable) {
+            AssignToLocalVariable assign = (AssignToLocalVariable) _instruction;
+            Instruction child = ((Instruction) assign).getFirstChild();
+
+            if (child instanceof CastOperator) {
+               child = child.getFirstChild();
+            }
+            if (child instanceof I_IADD) {
+               I_IADD add = (I_IADD) child;
+               Instruction lhs = add.getLhs();
+               Instruction rhs = add.getRhs();
+               if (lhs instanceof AccessLocalVariable) {
+                  AccessLocalVariable access = (AccessLocalVariable) lhs;
+                  if (access.getLocalVariableTableIndex() == assign.getLocalVariableTableIndex()) {
+                     if (rhs instanceof I_ICONST_1) {
+                        return (InstructionMatch.TRUE);
+                     }
+                  }
+               }
+            }
+         }
+         return (InstructionMatch.FALSE);
+      }
+
+   };
+
+   static final InstructionMatcher longHandDecLocalVariable = new InstructionMatcher("Long hand decrement of local variable"){
+      /**
+       * <pre>
+       *                                                   
+       *                  / iload<n>         
+       *  istore<n> - isub                       
+       *                  \ i_const_1   
+       *                  
+       *                          / iload<n>         
+       *  istore<n> - (?2i) - isub                       
+       *                          \ i_const_1    
+       *
+       * </pre>
+       */
+      @Override InstructionMatch matches(Instruction _instruction) {
+         if (_instruction instanceof AssignToLocalVariable) {
+            AssignToLocalVariable assign = (AssignToLocalVariable) _instruction;
+            Instruction child = ((Instruction) assign).getFirstChild();
+
+            if (child instanceof CastOperator) {
+               child = child.getFirstChild();
+            }
+            if (child instanceof I_ISUB) {
+               I_ISUB add = (I_ISUB) child;
+               Instruction lhs = add.getLhs();
+               Instruction rhs = add.getRhs();
+               if (lhs instanceof AccessLocalVariable) {
+                  AccessLocalVariable access = (AccessLocalVariable) lhs;
+                  if (access.getLocalVariableTableIndex() == assign.getLocalVariableTableIndex()) {
+                     if (rhs instanceof I_ICONST_1) {
+                        return (InstructionMatch.TRUE);
+                     }
+                  }
+               }
+            }
+         }
+         return (InstructionMatch.FALSE);
+      }
+
+   };
+
+   static final InstructionMatcher fieldPlusOne = new InstructionMatcher("Field Plus One"){
+      /**
+       * <pre>                                               
+       *                   / getfield<f>       
+       *         i2<t> iadd                          
+       *                   \ i_const_1    
+       *                         
+       *              / getfield<f>  
+       *         iadd              
+       *              \ i_const_1    
+       * </pre>
+       */
+      @Override InstructionMatch matches(Instruction _instruction) {
+
+         if (_instruction instanceof CastOperator) {
+            CastOperator topCastOperator = (CastOperator) _instruction;
+            _instruction = topCastOperator.getFirstChild().getReal();
+         }
+
+         if (_instruction instanceof I_IADD) {
+            I_IADD add = (I_IADD) _instruction;
+            Instruction addLhs = add.getLhs().getReal();
+            Instruction addRhs = add.getRhs().getReal();
+            if (addLhs instanceof AccessInstanceField) {
+               if (addRhs instanceof I_ICONST_1) {
+                  return (InstructionMatch.TRUE);
+               }
+            }
+         }
+         return (InstructionMatch.FALSE);
+      }
+
+   };
+
+   static final InstructionMatcher fieldMinusOne = new InstructionMatcher("Field minus 1"){
+      /**
+       * <pre>                                               
+       *                   / getfield<f>       
+       *         i2<t> isub                          
+       *                   \ i_const_1    
+       *                         
+       *              / getfield<f>  
+       *         isub              
+       *              \ i_const_1    
+       * </pre>
+       */
+      @Override InstructionMatch matches(Instruction _instruction) {
+
+         if (_instruction instanceof CastOperator) {
+            CastOperator topCastOperator = (CastOperator) _instruction;
+            _instruction = topCastOperator.getFirstChild().getReal();
+         }
+
+         if (_instruction instanceof I_ISUB) {
+            I_ISUB add = (I_ISUB) _instruction;
+            Instruction addLhs = add.getLhs().getReal();
+            Instruction addRhs = add.getRhs().getReal();
+            if (addLhs instanceof AccessInstanceField) {
+               if (addRhs instanceof I_ICONST_1) {
+                  return (InstructionMatch.TRUE);
+               }
+            }
+         }
+         return (InstructionMatch.FALSE);
+      }
+
+   };
+
+   static final InstructionMatcher fieldArrayElementAccess = new InstructionMatcher("Field array element access"){
+      /**
+       * 
+       * <pre>                                                
+       *                         
+       *              / getfield<f>  
+       *         iaload             
+       *              \ i_load    
+       * </pre>
+       */
+      @Override InstructionMatch matches(Instruction _instruction) {
+
+         if (_instruction instanceof AccessArrayElement) {
+            AccessArrayElement accessArrayElement = (AccessArrayElement) _instruction;
+            Instruction addLhs = accessArrayElement.getArrayRef().getReal();
+            // Instruction addRhs = accessArrayElement.getArrayIndex().getReal();
+            if (addLhs instanceof AccessInstanceField) {
+
+               return (InstructionMatch.TRUE);
+
+            }
+         }
+         return (InstructionMatch.FALSE);
+      }
+
+   };
+
+   static final InstructionMatcher fieldArrayElementPlusOne = new InstructionMatcher("field array element plus one"){
+      /**
+       * <pre>                                                
+       *                                         [       / getfield - aload_0 ]
+       *              / [fieldArrayElementAccess][ iaload                     ]
+       *         iadd                            [       \ iload              ]
+       *              \ iconst_1    
+       * </pre>
+       */
+      @Override InstructionMatch matches(Instruction _instruction) {
+         if (_instruction instanceof I_IADD) {
+            I_IADD accessArrayElement = (I_IADD) _instruction;
+            if (accessArrayElement.getLhs() != null) {
+               Instruction addLhs = accessArrayElement.getLhs().getReal();
+               if (fieldArrayElementAccess.matches(addLhs).ok) {
+                  Instruction addRhs = accessArrayElement.getRhs().getReal();
+                  if (addRhs instanceof I_ICONST_1) {
+                     return (InstructionMatch.TRUE);
+                  }
+               }
+            }
+         }
+         return (InstructionMatch.FALSE);
+      }
+
+   };
+
+   static final InstructionMatcher fieldArrayElementMinusOne = new InstructionMatcher("field array element minus one"){
+      /**
+       * <pre>                                                
+       *                                         [       / getfield - aload_0 ]
+       *              / [fieldArrayElementAccess][ iaload                     ]
+       *         isub                            [       \ iload              ]
+       *              \ iconst_1    
+       * </pre>
+       */
+      @Override InstructionMatch matches(Instruction _instruction) {
+         if (_instruction instanceof I_ISUB) {
+            I_ISUB accessArrayElement = (I_ISUB) _instruction;
+            Instruction addLhs = accessArrayElement.getLhs().getReal();
+            if (fieldArrayElementAccess.matches(addLhs).ok) {
+               Instruction addRhs = accessArrayElement.getRhs().getReal();
+               if (addRhs instanceof I_ICONST_1) {
+                  return (InstructionMatch.TRUE);
+               }
+            }
+         }
+         return (InstructionMatch.FALSE);
+      }
+
+   };
+
+   static final InstructionMatcher longHandFieldArrayElementIncrement = new InstructionMatcher(
+         "long hand field array element increment"){
+      /**
+       * //iastore{9:getfield{8:aload_0} ,12:iload_1 ,17:iadd{14:iaload{*9:getfield{8:aload_0} ,*12:iload_1} ,16:iconst_1}}
+       * <pre>                                                
+       *                         
+       *                  / getfield - aload  
+       *         iastore -  iload                                                    
+       *                  \ [fieldArrayElementPlusOne]     
+       * </pre>
+       */
+      @Override InstructionMatch matches(Instruction _instruction) {
+
+         if (_instruction instanceof AssignToArrayElement) {
+            AssignToArrayElement accessArrayElement = (AssignToArrayElement) _instruction;
+            Instruction arrayRef = accessArrayElement.getArrayRef().getReal();
+            //  Instruction arrayIndex = accessArrayElement.getArrayIndex().getReal();
+            Instruction value = accessArrayElement.getValue().getReal();
+            // Instruction addRhs = accessArrayElement.getArrayIndex().getReal();
+            if (arrayRef instanceof AccessInstanceField) {
+               if (fieldArrayElementPlusOne.matches(value).ok) {
+                  return (InstructionMatch.TRUE);
+               }
+            }
+         }
+         return (InstructionMatch.FALSE);
+      }
+
+   };
+
+   static final InstructionMatcher longHandFieldArrayElementDecrement = new InstructionMatcher(
+         "long hand field array element decrement"){
+      /**
+       * //iastore{9:getfield{8:aload_0} ,12:iload_1 ,17:iadd{14:iaload{*9:getfield{8:aload_0} ,*12:iload_1} ,16:iconst_1}}
+       * <pre>                                                
+       *                         
+       *                  / getfield - aload  
+       *         iastore -  iload                                                    
+       *                  \ [fieldArrayElementPlusOne]     
+       * </pre>
+       */
+      @Override InstructionMatch matches(Instruction _instruction) {
+
+         if (_instruction instanceof AssignToArrayElement) {
+            AssignToArrayElement accessArrayElement = (AssignToArrayElement) _instruction;
+            Instruction arrayRef = accessArrayElement.getArrayRef().getReal();
+            //  Instruction arrayIndex = accessArrayElement.getArrayIndex().getReal();
+            Instruction value = accessArrayElement.getValue().getReal();
+            // Instruction addRhs = accessArrayElement.getArrayIndex().getReal();
+            if (arrayRef instanceof AccessInstanceField) {
+               if (fieldArrayElementMinusOne.matches(value).ok) {
+                  return (InstructionMatch.TRUE);
+               }
+            }
+         }
+         return (InstructionMatch.FALSE);
+      }
+
+   };
+
+   static final InstructionMatcher accessLocalVariable = new InstructionMatcher("access to local variable"){
+
+      @Override InstructionMatch matches(Instruction _instruction) {
+         return (InstructionMatch.test(_instruction instanceof AccessLocalVariable));
+      }
+
+   };
+
+   static final InstructionMatcher inc = new InstructionMatcher("inc"){
+
+      @Override InstructionMatch matches(Instruction _instruction) {
+         return (InstructionMatch.test(_instruction instanceof I_IINC));
+      }
+
+   };
+
+   static final InstructionMatcher cast = new InstructionMatcher("cast"){
+
+      @Override InstructionMatch matches(Instruction _instruction) {
+         return (InstructionMatch.test(_instruction instanceof CastOperator));
+      }
+
+   };
+
+   static final InstructionMatcher accessInstanceField = new InstructionMatcher("access instance field"){
+
+      @Override InstructionMatch matches(Instruction _instruction) {
+         return (InstructionMatch.test(_instruction instanceof AccessInstanceField));
+      }
+
+   };
+
+   static final InstructionMatcher assignToInstanceField = new InstructionMatcher("assign to instance field"){
+
+      @Override InstructionMatch matches(Instruction _instruction) {
+         return (InstructionMatch.test(_instruction instanceof AssignToInstanceField));
+      }
+
+   };
+
+   static final InstructionMatcher iadd = new InstructionMatcher("iadd"){
+
+      @Override InstructionMatch matches(Instruction _instruction) {
+         return (InstructionMatch.test(_instruction instanceof I_IADD));
+      }
+
+   };
+
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/InstructionSet.java b/com.amd.aparapi/src/java/com/amd/aparapi/InstructionSet.java
new file mode 100644
index 00000000..8188a83d
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/InstructionSet.java
@@ -0,0 +1,4273 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import com.amd.aparapi.ClassModel.ConstantPool;
+import com.amd.aparapi.ClassModel.AttributePool.LocalVariableTableEntry;
+import com.amd.aparapi.ClassModel.AttributePool.LocalVariableTableEntry.LocalVariableInfo;
+import com.amd.aparapi.ClassModel.ConstantPool.Entry;
+import com.amd.aparapi.ClassModel.ConstantPool.FieldEntry;
+import com.amd.aparapi.ClassModel.ConstantPool.MethodEntry;
+
+class InstructionSet{
+
+   static enum TypeSpec {
+      NONE("none", "none", 0, 0), //
+      Z("Z", "boolean", 4, 1), // Note 'Z' is the java code for 'boolean' type
+      C("C", "char", 2, 1), //
+      F("F", "float", 4, 1), //
+      D("D", "double", 8, 2), //
+      B("B", "byte", 1, 1), //
+      S("S", "short", 2, 1), //
+      I("I", "int", 4, 1), //
+      L("L", "long", 8, 1), // 
+      J("J", "long", 8, 1), // Note J is the java code for 'long' type
+      A("A", "array", 4, 1), //
+      O("O", "object", 4, 1),
+      N("N", "null", 4, 1),
+      IorForS("IorForS", "int, float or String depending on constant pool entry", 4, 1),
+      LorD("LorD", "long or float depending upon the constant pool entry", 8, 2),
+      RA("RA", "return address", 4, 1),
+      UNKNOWN("UNKNOWN", "unknown", -1, -1),
+      ARGS("ARGS", "args to method call", -1, -1);
+
+      private String longName;
+
+      private String shortName;
+
+      private int size;
+
+      private int slots;
+
+      TypeSpec(String _shortName, String _longName, int _size, int _slots) {
+         shortName = _shortName;
+         longName = _longName;
+         size = _size;
+         slots = _slots;
+      }
+
+      int getSize() {
+         return (size);
+      }
+
+      int getSlots() {
+         return (slots);
+      }
+
+      String getLongName() {
+         return (longName);
+      }
+
+      String getShortName() {
+         return (shortName);
+      }
+
+   }
+
+   /**
+    * Represents an Operator
+    * 
+    * @author gfrost
+    *
+    */
+
+   static enum Operator {
+      NONE,
+      LogicalOr(true, "||"), //
+      LogicalAnd(true, "&&", LogicalOr), //
+      Equal(true, "=="), //
+      NotEqual(true, "!=", Equal), //
+      LessThan(true, "<"), //
+      GreaterThanOrEqual(true, ">=", LessThan), //
+      GreaterThan(true, ">"), //
+      LessThanOrEqual(true, "<=", GreaterThan), //
+      EqualNULL(true, "NULL=="),
+      NotEqualNULL(true, "NULL!=", EqualNULL), //
+
+      BitwiseOr(true, "|"), //
+      BitwiseAnd(true, "&"), //
+      BitwiseXor(true, "^"),
+
+      LeftShift(true, "<<"), //
+      ArithmeticRightShift(true, ">>>"), //
+      LogicalRightShift(true, ">>"), //  was >>> but this caused issues in opencl 
+
+      Add(true, "+"), //
+      Sub(true, "-"), //
+
+      Div(true, "/"), //
+      Rem(true, "%"), //
+      Mul(true, "*"), //
+
+      Neg(false, "-"), //
+      Pos(false, "+"), //
+
+      I2FCast(false, "(float)"),
+      I2LCast(false, "(long)"), //
+      I2DCast(false, "(double)"), //
+      L2ICast(false, "(int)"), //
+      L2FCast(false, "(float)"), //
+      L2DCast(false, "(double)"), //
+      F2ICast(false, "(int)"), //
+      F2LCast(false, "(long)"), //
+      F2DCast(false, "(double)"), //
+      D2ICast(false, "(int)"), //
+      D2LCast(false, "(long)"), //
+      D2FCast(false, "(float)"), //
+      I2BCast(false, "(byte)"), //
+      I2CCast(false, "(char)"), //
+      I2SCast(false, "(short)");
+
+      private String text;
+
+      private boolean binary;
+
+      private Operator compliment;
+
+      Operator(boolean _binary, String _text) {
+
+         text = _text;
+         binary = _binary;
+      }
+
+      Operator(boolean _binary, String _text, Operator _c) {
+         this(_binary, _text);
+         compliment = _c;
+         compliment.compliment = this;
+      }
+
+      Operator() {
+         this(false, null);
+      }
+
+      String getText() {
+         return text;
+      }
+
+      Operator getCompliment() {
+         return (compliment);
+      }
+
+      String getText(boolean _invert) {
+         return (_invert ? compliment.getText() : getText());
+      }
+
+      boolean isBinary() {
+         return (binary);
+
+      }
+
+      boolean isUnary() {
+         return (!this.equals(Operator.NONE) && !isBinary());
+
+      }
+   }
+
+   static enum PushSpec {
+      NONE, //
+      UNKNOWN, //
+      I(TypeSpec.I), //
+      II(TypeSpec.I, TypeSpec.I), //
+      III(TypeSpec.I, TypeSpec.I, TypeSpec.I), //
+      IIII(TypeSpec.I, TypeSpec.I, TypeSpec.I, TypeSpec.I), //
+      IIIII(TypeSpec.I, TypeSpec.I, TypeSpec.I, TypeSpec.I, TypeSpec.I), //
+      IIIIII(TypeSpec.I, TypeSpec.I, TypeSpec.I, TypeSpec.I, TypeSpec.I, TypeSpec.I), //
+      L(TypeSpec.L), //
+      F(TypeSpec.F), //
+      D(TypeSpec.D), //
+      O(TypeSpec.O), //
+      A(TypeSpec.A), //
+      N(TypeSpec.N), //
+      IorForS(TypeSpec.IorForS), //
+      LorD(TypeSpec.LorD), //
+      RA(TypeSpec.RA);
+
+      PushSpec(TypeSpec... _types) {
+         types = _types;
+      }
+
+      private TypeSpec[] types;
+
+      int getStackAdjust() {
+         return (types.length);
+      }
+   }
+
+   static enum PopSpec {
+      NONE, //
+      UNKNOWN(TypeSpec.UNKNOWN), //
+      I(TypeSpec.I), //
+      II(TypeSpec.I, TypeSpec.I), //
+      III(TypeSpec.I, TypeSpec.I, TypeSpec.I), //
+      IIII(TypeSpec.I, TypeSpec.I, TypeSpec.I, TypeSpec.I), //
+      IIIII(TypeSpec.I, TypeSpec.I, TypeSpec.I, TypeSpec.I, TypeSpec.I), //
+      L(TypeSpec.L), //
+      LL(TypeSpec.L, TypeSpec.L), //
+      F(TypeSpec.F), //
+      FF(TypeSpec.F, TypeSpec.F), //
+      D(TypeSpec.D), //
+      DD(TypeSpec.D, TypeSpec.D), //
+      O(TypeSpec.O), //
+      OO(TypeSpec.O, TypeSpec.O), //
+      A(TypeSpec.A), //
+      AI(TypeSpec.A, TypeSpec.I), //
+      AII(TypeSpec.A, TypeSpec.I, TypeSpec.I), //
+      AIF(TypeSpec.A, TypeSpec.I, TypeSpec.F), //
+      AID(TypeSpec.A, TypeSpec.I, TypeSpec.D), //
+      AIL(TypeSpec.A, TypeSpec.I, TypeSpec.L), //
+      AIC(TypeSpec.A, TypeSpec.I, TypeSpec.C), //
+      AIS(TypeSpec.A, TypeSpec.I, TypeSpec.S), //
+      AIB(TypeSpec.A, TypeSpec.I, TypeSpec.B), //
+      AIO(TypeSpec.A, TypeSpec.I, TypeSpec.O), //
+      LI(TypeSpec.L, TypeSpec.I), //
+      OUNKNOWN(TypeSpec.O, TypeSpec.UNKNOWN), //
+      ARGS(TypeSpec.ARGS), //
+      OARGS(TypeSpec.O, TypeSpec.ARGS), //
+      ;
+
+      PopSpec(TypeSpec... _types) {
+         types = _types;
+      }
+
+      private TypeSpec[] types;
+
+      int getStackAdjust() {
+         return (types.length);
+      }
+
+   }
+
+   static enum ImmediateSpec {
+      NONE("NONE"), //
+      UNKNOWN("UNKNOWN"), //
+      Bconst("byte constant value", TypeSpec.B), //
+      Sconst("short constant value", TypeSpec.S), //
+      Bcpci("byte constant pool constant index", TypeSpec.B), //
+      Scpci("short constant pool constant index", TypeSpec.S), //
+      Icpci("int constant pool index", TypeSpec.I), //
+      Blvti("byte local variable table index", TypeSpec.B),
+      Spc("short pc", TypeSpec.S),
+      Ipc("int pc", TypeSpec.I),
+      Scpfi("short constant pool field index", TypeSpec.S),
+      Scpmi("short constant pool method index", TypeSpec.S),
+      ScpmiBB("short constant pool method index, byte count, byte (always zero)", TypeSpec.S, TypeSpec.B, TypeSpec.B),
+      ScpciBdim("short constant pool class index, byte dimensions", TypeSpec.S, TypeSpec.B),
+      BlvtiBconst("byte local variable table index, byte constant value", TypeSpec.B, TypeSpec.B);
+
+      private String name;
+
+      ImmediateSpec(String _name, TypeSpec... _types) {
+
+         name = _name;
+         types = _types;
+      }
+
+      private TypeSpec[] types;
+
+      String getName() {
+         return (name);
+      }
+
+      TypeSpec[] getTypes() {
+         return (types);
+      }
+
+   }
+
+   static enum ByteCode {
+      // name, operation type, immediateOperands, pop operands, push operands
+      NOP(null, ImmediateSpec.NONE, PopSpec.NONE, PushSpec.NONE, Operator.NONE), //
+      ACONST_NULL(I_ACONST_NULL.class, PushSpec.N), //
+      ICONST_M1(I_ICONST_M1.class, PushSpec.I), //
+      ICONST_0(I_ICONST_0.class, PushSpec.I), // 
+      ICONST_1(I_ICONST_1.class, PushSpec.I), // 
+      ICONST_2(I_ICONST_2.class, PushSpec.I), // 
+      ICONST_3(I_ICONST_3.class, PushSpec.I), // 
+      ICONST_4(I_ICONST_4.class, PushSpec.I), // 
+      ICONST_5(I_ICONST_5.class, PushSpec.I), // 
+      LCONST_0(I_LCONST_0.class, PushSpec.L), // 
+      LCONST_1(I_LCONST_1.class, PushSpec.L), // 
+      FCONST_0(I_FCONST_0.class, PushSpec.F), //
+      FCONST_1(I_FCONST_1.class, PushSpec.F), //
+      FCONST_2(I_FCONST_2.class, PushSpec.F), //
+      DCONST_0(I_DCONST_0.class, PushSpec.D), //
+      DCONST_1(I_DCONST_1.class, PushSpec.D), //
+      BIPUSH(I_BIPUSH.class, ImmediateSpec.Bconst, PushSpec.I), //
+      SIPUSH(I_SIPUSH.class, ImmediateSpec.Sconst, PushSpec.I), //
+      LDC(I_LDC.class, ImmediateSpec.Bcpci, PushSpec.IorForS), //
+      LDC_W(I_LDC_W.class, ImmediateSpec.Scpci, PushSpec.IorForS), //
+      LDC2_W(I_LDC2_W.class, ImmediateSpec.Scpci, PushSpec.LorD), //
+      ILOAD(I_ILOAD.class, ImmediateSpec.Blvti, PushSpec.I), //
+      LLOAD(I_LLOAD.class, ImmediateSpec.Blvti, PushSpec.L), //
+      FLOAD(I_FLOAD.class, ImmediateSpec.Blvti, PushSpec.F), //
+      DLOAD(I_DLOAD.class, ImmediateSpec.Blvti, PushSpec.D), //
+      ALOAD(I_ALOAD.class, ImmediateSpec.Blvti, PushSpec.O), //
+      ILOAD_0(I_ILOAD_0.class, PushSpec.I), //
+      ILOAD_1(I_ILOAD_1.class, PushSpec.I), //
+      ILOAD_2(I_ILOAD_2.class, PushSpec.I), //
+      ILOAD_3(I_ILOAD_3.class, PushSpec.I), //
+      LLOAD_0(I_LLOAD_0.class, PushSpec.L), //
+      LLOAD_1(I_LLOAD_1.class, PushSpec.L), //
+      LLOAD_2(I_LLOAD_2.class, PushSpec.L), //
+      LLOAD_3(I_LLOAD_3.class, PushSpec.L), //
+      FLOAD_0(I_FLOAD_0.class, PushSpec.F), //
+      FLOAD_1(I_FLOAD_1.class, PushSpec.F), //
+      FLOAD_2(I_FLOAD_2.class, PushSpec.F), //
+      FLOAD_3(I_FLOAD_3.class, PushSpec.F), //
+      DLOAD_0(I_DLOAD_0.class, PushSpec.D), //
+      DLOAD_1(I_DLOAD_1.class, PushSpec.D), //
+      DLOAD_2(I_DLOAD_2.class, PushSpec.D), //
+      DLOAD_3(I_DLOAD_3.class, PushSpec.D), //
+      ALOAD_0(I_ALOAD_0.class, PushSpec.O), //
+      ALOAD_1(I_ALOAD_1.class, PushSpec.O), //
+      ALOAD_2(I_ALOAD_2.class, PushSpec.O), //
+      ALOAD_3(I_ALOAD_3.class, PushSpec.O), //
+      IALOAD(I_IALOAD.class, PopSpec.AI, PushSpec.I), //
+      LALOAD(I_LALOAD.class, PopSpec.AI, PushSpec.L), //
+      FALOAD(I_FALOAD.class, PopSpec.AI, PushSpec.F), //
+      DALOAD(I_DALOAD.class, PopSpec.AI, PushSpec.D), //
+      AALOAD(I_AALOAD.class, PopSpec.AI, PushSpec.A), //
+      BALOAD(I_BALOAD.class, PopSpec.AI, PushSpec.I), //
+      CALOAD(I_CALOAD.class, PopSpec.AI, PushSpec.I), //
+      SALOAD(I_SALOAD.class, PopSpec.AI, PushSpec.I), //
+      ISTORE(I_ISTORE.class, ImmediateSpec.Blvti, PopSpec.I), //
+      LSTORE(I_LSTORE.class, ImmediateSpec.Blvti, PopSpec.L), //
+      FSTORE(I_FSTORE.class, ImmediateSpec.Blvti, PopSpec.F), //
+      DSTORE(I_DSTORE.class, ImmediateSpec.Blvti, PopSpec.D), //
+      ASTORE(I_ASTORE.class, ImmediateSpec.Blvti, PopSpec.O), //
+      ISTORE_0(I_ISTORE_0.class, PopSpec.I), //
+      ISTORE_1(I_ISTORE_1.class, PopSpec.I), //
+      ISTORE_2(I_ISTORE_2.class, PopSpec.I), //
+      ISTORE_3(I_ISTORE_3.class, PopSpec.I), //
+      LSTORE_0(I_LSTORE_0.class, PopSpec.L), //
+      LSTORE_1(I_LSTORE_1.class, PopSpec.L), //
+      LSTORE_2(I_LSTORE_2.class, PopSpec.L), //
+      LSTORE_3(I_LSTORE_3.class, PopSpec.L), //
+      FSTORE_0(I_FSTORE_0.class, PopSpec.F), //
+      FSTORE_1(I_FSTORE_1.class, PopSpec.F), //
+      FSTORE_2(I_FSTORE_2.class, PopSpec.F), //
+      FSTORE_3(I_FSTORE_3.class, PopSpec.F), //
+      DSTORE_0(I_DSTORE_0.class, PopSpec.D), //
+      DSTORE_1(I_DSTORE_1.class, PopSpec.D), //
+      DSTORE_2(I_DSTORE_2.class, PopSpec.D), //
+      DSTORE_3(I_DSTORE_3.class, PopSpec.D), //
+      ASTORE_0(I_ASTORE_0.class, PopSpec.O), //
+      ASTORE_1(I_ASTORE_1.class, PopSpec.O), //
+      ASTORE_2(I_ASTORE_2.class, PopSpec.O), //
+      ASTORE_3(I_ASTORE_3.class, PopSpec.O), //
+      IASTORE(I_IASTORE.class, PopSpec.AII), //
+      LASTORE(I_LASTORE.class, PopSpec.AIL), //
+      FASTORE(I_FASTORE.class, PopSpec.AIF), //
+      DASTORE(I_DASTORE.class, PopSpec.AID), //
+      AASTORE(I_AASTORE.class, PopSpec.AIO), //
+      BASTORE(I_BASTORE.class, PopSpec.AIB), //
+      CASTORE(I_CASTORE.class, PopSpec.AIC), //
+      SASTORE(I_SASTORE.class, PopSpec.AIS), //
+      POP(I_POP.class, PopSpec.I), //
+      POP2(I_POP2.class, PopSpec.II), //
+      DUP(I_DUP.class, PopSpec.I, PushSpec.II), //
+      DUP_X1(I_DUP_X1.class, PopSpec.II, PushSpec.III), //
+      DUP_X2(I_DUP_X2.class, PopSpec.III, PushSpec.IIII), //
+      DUP2(I_DUP2.class, PopSpec.II, PushSpec.IIII), //
+      DUP2_X1(I_DUP2_X1.class, PopSpec.III, PushSpec.IIIII), //
+      DUP2_X2(I_DUP2_X2.class, PopSpec.IIII, PushSpec.IIIIII), //
+      SWAP(I_SWAP.class, PopSpec.II, PushSpec.II), // ..., value2, value1 => ..., value1,
+      // value2
+      IADD(I_IADD.class, PopSpec.II, PushSpec.I, Operator.Add), //
+      LADD(I_LADD.class, PopSpec.LL, PushSpec.L, Operator.Add), //
+      FADD(I_FADD.class, PopSpec.FF, PushSpec.F, Operator.Add), //
+      DADD(I_DADD.class, PopSpec.DD, PushSpec.D, Operator.Add), //
+      ISUB(I_ISUB.class, PopSpec.II, PushSpec.I, Operator.Sub), //
+      LSUB(I_LSUB.class, PopSpec.LL, PushSpec.L, Operator.Sub), //
+      FSUB(I_FSUB.class, PopSpec.FF, PushSpec.F, Operator.Sub), //
+      DSUB(I_DSUB.class, PopSpec.DD, PushSpec.D, Operator.Sub), //
+      IMUL(I_IMUL.class, PopSpec.II, PushSpec.I, Operator.Mul), //
+      LMUL(I_LMUL.class, PopSpec.LL, PushSpec.L, Operator.Mul), //
+      FMUL(I_FMUL.class, PopSpec.FF, PushSpec.F, Operator.Mul), //
+      DMUL(I_DMUL.class, PopSpec.DD, PushSpec.D, Operator.Mul), //
+      IDIV(I_IDIV.class, PopSpec.II, PushSpec.I, Operator.Div), //
+      LDIV(I_LDIV.class, PopSpec.LL, PushSpec.L, Operator.Div), //
+      FDIV(I_FDIV.class, PopSpec.FF, PushSpec.F, Operator.Div), //
+      DDIV(I_DDIV.class, PopSpec.DD, PushSpec.D, Operator.Div), //
+      IREM(I_IREM.class, PopSpec.II, PushSpec.I, Operator.Rem), //
+      LREM(I_LREM.class, PopSpec.LL, PushSpec.L, Operator.Rem), //
+      FREM(I_FREM.class, PopSpec.FF, PushSpec.F, Operator.Rem), //
+      DREM(I_DREM.class, PopSpec.DD, PushSpec.D, Operator.Rem), //
+      INEG(I_INEG.class, PopSpec.I, PushSpec.I, Operator.Neg), //
+      LNEG(I_LNEG.class, PopSpec.L, PushSpec.L, Operator.Neg), //
+      FNEG(I_FNEG.class, PopSpec.F, PushSpec.F, Operator.Neg), //
+      DNEG(I_DNEG.class, PopSpec.D, PushSpec.D, Operator.Neg), //
+      ISHL(I_ISHL.class, PopSpec.II, PushSpec.I, Operator.LeftShift), //
+      LSHL(I_LSHL.class, PopSpec.LI, PushSpec.L, Operator.LeftShift), //
+      ISHR(I_ISHR.class, PopSpec.II, PushSpec.I, Operator.LogicalRightShift), //
+      LSHR(I_LSHR.class, PopSpec.LI, PushSpec.L, Operator.LogicalRightShift), //
+      IUSHR(I_IUSHR.class, PopSpec.II, PushSpec.I, Operator.ArithmeticRightShift), //
+      LUSHR(I_LUSHR.class, PopSpec.LI, PushSpec.L, Operator.ArithmeticRightShift), //
+      IAND(I_IAND.class, PopSpec.II, PushSpec.I, Operator.BitwiseAnd), //
+      LAND(I_LAND.class, PopSpec.LL, PushSpec.L, Operator.BitwiseAnd), //
+      IOR(I_IOR.class, PopSpec.II, PushSpec.I, Operator.BitwiseOr), //
+      LOR(I_LOR.class, PopSpec.LL, PushSpec.L, Operator.BitwiseOr), //
+      IXOR(I_IXOR.class, PopSpec.II, PushSpec.I, Operator.BitwiseXor), //
+      LXOR(I_LXOR.class, PopSpec.LL, PushSpec.L, Operator.BitwiseXor), //
+      IINC(I_IINC.class, ImmediateSpec.BlvtiBconst), //
+      I2L(I_I2L.class, PopSpec.I, PushSpec.L, Operator.I2LCast), //
+      I2F(I_I2F.class, PopSpec.I, PushSpec.F, Operator.I2FCast), //
+      I2D(I_I2D.class, PopSpec.I, PushSpec.D, Operator.I2DCast), //
+      L2I(I_L2I.class, PopSpec.L, PushSpec.I, Operator.L2ICast), //
+      L2F(I_L2F.class, PopSpec.L, PushSpec.F, Operator.L2FCast), //
+      L2D(I_L2D.class, PopSpec.L, PushSpec.D, Operator.L2DCast), //
+      F2I(I_F2I.class, PopSpec.F, PushSpec.I, Operator.F2ICast), //
+      F2L(I_F2L.class, PopSpec.F, PushSpec.L, Operator.F2LCast), //
+      F2D(I_F2D.class, PopSpec.F, PushSpec.D, Operator.F2DCast), //
+      D2I(I_D2I.class, PopSpec.D, PushSpec.I, Operator.D2ICast), //
+      D2L(I_D2L.class, PopSpec.D, PushSpec.L, Operator.D2LCast), //
+      D2F(I_D2F.class, PopSpec.D, PushSpec.F, Operator.D2FCast), //
+      I2B(I_I2B.class, PopSpec.I, PushSpec.I, Operator.I2BCast), //
+      I2C(I_I2C.class, PopSpec.I, PushSpec.I, Operator.I2CCast), //
+      I2S(I_I2S.class, PopSpec.I, PushSpec.I, Operator.I2SCast), //
+      LCMP(I_LCMP.class, PopSpec.LL, PushSpec.I, Operator.Sub), //
+      FCMPL(I_FCMPL.class, PopSpec.FF, PushSpec.I, Operator.LessThan), //
+      FCMPG(I_FCMPG.class, PopSpec.FF, PushSpec.I, Operator.GreaterThan), //
+      DCMPL(I_DCMPL.class, PopSpec.DD, PushSpec.I, Operator.LessThan), //
+      DCMPG(I_DCMPG.class, PopSpec.DD, PushSpec.I, Operator.GreaterThan), //
+      IFEQ(I_IFEQ.class, ImmediateSpec.Spc, PopSpec.I, Operator.Equal), //
+      IFNE(I_IFNE.class, ImmediateSpec.Spc, PopSpec.I, Operator.NotEqual), //
+      IFLT(I_IFLT.class, ImmediateSpec.Spc, PopSpec.I, Operator.LessThan), //
+      IFGE(I_IFGE.class, ImmediateSpec.Spc, PopSpec.I, Operator.GreaterThanOrEqual), //
+      IFGT(I_IFGT.class, ImmediateSpec.Spc, PopSpec.I, Operator.GreaterThan), //
+      IFLE(I_IFLE.class, ImmediateSpec.Spc, PopSpec.I, Operator.LessThanOrEqual), //
+      IF_ICMPEQ(I_IF_ICMPEQ.class, ImmediateSpec.Sconst, PopSpec.II, Operator.Equal), //
+      IF_ICMPNE(I_IF_ICMPNE.class, ImmediateSpec.Spc, PopSpec.II, Operator.NotEqual), //
+      IF_ICMPLT(I_IF_ICMPLT.class, ImmediateSpec.Spc, PopSpec.II, Operator.LessThan), //
+      IF_ICMPGE(I_IF_ICMPGE.class, ImmediateSpec.Spc, PopSpec.II, Operator.GreaterThanOrEqual), //
+      IF_ICMPGT(I_IF_ICMPGT.class, ImmediateSpec.Spc, PopSpec.II, Operator.GreaterThan), //
+      IF_ICMPLE(I_IF_ICMPLE.class, ImmediateSpec.Spc, PopSpec.II, Operator.LessThanOrEqual), //
+      IF_ACMPEQ(I_IF_ACMPEQ.class, ImmediateSpec.Spc, PopSpec.OO, Operator.Equal), //
+      IF_ACMPNE(I_IF_ACMPNE.class, ImmediateSpec.Spc, PopSpec.OO, Operator.NotEqual), //
+      GOTO(I_GOTO.class, ImmediateSpec.Spc), //
+      JSR(I_JSR.class, ImmediateSpec.Spc, PushSpec.RA), //
+      RET(I_RET.class, ImmediateSpec.Bconst), //
+      TABLESWITCH(I_TABLESWITCH.class, ImmediateSpec.UNKNOWN, PopSpec.I), //
+      LOOKUPSWITCH(I_LOOKUPSWITCH.class, ImmediateSpec.UNKNOWN, PopSpec.I), //
+      IRETURN(I_IRETURN.class, PopSpec.I), //
+      LRETURN(I_LRETURN.class, PopSpec.L), //
+      FRETURN(I_FRETURN.class, PopSpec.F), //
+      DRETURN(I_DRETURN.class, PopSpec.D), //
+      ARETURN(I_ARETURN.class, PopSpec.O), //
+      RETURN(I_RETURN.class, ImmediateSpec.NONE, PopSpec.NONE, PushSpec.NONE, Operator.NONE), //
+      GETSTATIC(I_GETSTATIC.class, ImmediateSpec.Scpfi, PushSpec.UNKNOWN), //
+      PUTSTATIC(I_PUTSTATIC.class, ImmediateSpec.Scpfi, PopSpec.UNKNOWN), //
+      GETFIELD(I_GETFIELD.class, ImmediateSpec.Scpfi, PopSpec.O, PushSpec.UNKNOWN, Operator.NONE), //
+      PUTFIELD(I_PUTFIELD.class, ImmediateSpec.Scpfi, PopSpec.OUNKNOWN), //
+      INVOKEVIRTUAL(I_INVOKEVIRTUAL.class, ImmediateSpec.Scpmi, PopSpec.OARGS, PushSpec.UNKNOWN, Operator.NONE), //
+      INVOKESPECIAL(I_INVOKESPECIAL.class, ImmediateSpec.Scpmi, PopSpec.OARGS, PushSpec.UNKNOWN, Operator.NONE), //
+      INVOKESTATIC(I_INVOKESTATIC.class, ImmediateSpec.Scpmi, PopSpec.ARGS, PushSpec.UNKNOWN, Operator.NONE), //
+      INVOKEINTERFACE(I_INVOKEINTERFACE.class, ImmediateSpec.ScpmiBB, PopSpec.OARGS, PushSpec.UNKNOWN, Operator.NONE), //
+      INVOKEDYNAMIC(I_INVOKEDYNAMIC.class, ImmediateSpec.ScpmiBB, PopSpec.OARGS, PushSpec.UNKNOWN, Operator.NONE), //
+
+      NEW(I_NEW.class, ImmediateSpec.Scpci, PushSpec.O), //
+      NEWARRAY(I_NEWARRAY.class, ImmediateSpec.Bconst, PopSpec.I, PushSpec.A, Operator.NONE), //
+      ANEWARRAY(I_ANEWARRAY.class, ImmediateSpec.Sconst, PopSpec.I, PushSpec.A, Operator.NONE), // 189
+      ARRAYLENGTH(I_ARRAYLENGTH.class, PopSpec.A, PushSpec.I), // 190
+      ATHROW(I_ATHROW.class, PopSpec.O, PushSpec.O), // 191
+      CHECKCAST(I_CHECKCAST.class, ImmediateSpec.Scpci, PopSpec.O, PushSpec.O, Operator.NONE), // 192
+      INSTANCEOF(I_INSTANCEOF.class, ImmediateSpec.Scpci, PopSpec.O, PushSpec.I, Operator.NONE), // 193
+      MONITORENTER(I_MONITORENTER.class, PopSpec.O), // 194
+      MONITOREXIT(I_MONITOREXIT.class, PopSpec.O), // 195
+      WIDE(I_WIDE.class, ImmediateSpec.UNKNOWN, PopSpec.UNKNOWN, PushSpec.UNKNOWN, Operator.NONE), // 196
+      MULTIANEWARRAY(I_MULTIANEWARRAY.class, ImmediateSpec.ScpciBdim, PopSpec.UNKNOWN, PushSpec.A, Operator.NONE), // 197
+      IFNULL(I_IFNULL.class, ImmediateSpec.Spc, PopSpec.O, Operator.EqualNULL), // 198
+      IFNONNULL(I_IFNONNULL.class, ImmediateSpec.Spc, PopSpec.O, Operator.NotEqualNULL), // 199
+      GOTO_W(I_GOTO_W.class, ImmediateSpec.Ipc), // 200
+      JSR_W(I_JSR_W.class, ImmediateSpec.Ipc, PushSpec.RA), // 201
+      ILLEGAL_202, // BREAKPOINT("breakpoint"),
+      ILLEGAL_203, // LDC_QUICK("ldc_quick"),
+      ILLEGAL_204, // LDC_W_QUICK("ldc_w_quick"),
+      ILLEGAL_205, // LDC2_W_QUICK("ldc2_w_quick"),
+      ILLEGAL_206, // GETFIELD_QUICK("getfield_quick"),
+      ILLEGAL_207, // PUTFIELD_QUICK("putfield_quick"),
+      ILLEGAL_208, // GETFIELD2_QUICK("getfield2_quick"),
+      ILLEGAL_209, // PUTFIELD2_QUICK("putfield2_quick"),
+      ILLEGAL_210, // GETSTATIC_QUICK("getstatic_quick"),
+      ILLEGAL_211, // PUTSTATIC_QUICK("putstatic_quick"),
+      ILLEGAL_212, // GETSTATIC2_QUICK("getstatic2_quick"),
+      ILLEGAL_213, // PUTSTATIC2_QUICK("putstatic2_quick"),
+      ILLEGAL_214, // INVOKEVIRTUAL_QUICK("invokevirtual_quick"),
+      ILLEGAL_215, // INVOKENONVIRTUAL_QUICK("invokenonvirtual_quick"),
+      ILLEGAL_216, // INVOKESUPER_QUICK("invokesuper_quick"),
+      ILLEGAL_217, // INVOKESTATIC_QUICK("invokestatic_quick"),
+      ILLEGAL_218, // INVOKEINTERFACE_QUICK("invokeinterface_quick"),
+      ILLEGAL_219, // INVOKEVIRTUALOBJECT_QUICK("invokevirtualobject_quick"),
+      ILLEGAL_220, // 220
+      ILLEGAL_221, // NEW_QUICK("new_quick"),
+      ILLEGAL_222, // ANEWARRAY_QUICK("anewarray_quick"),
+      ILLEGAL_223, // MULTIANEWARRAY_QUICK("multianewarray_quick"),
+      ILLEGAL_224, // CHECKCAST_QUICK("checkcast_quick"),
+      ILLEGAL_225, // INSTANCEOF_QUICK("instanceof_quick"),
+      ILLEGAL_226, // INVOKEVIRTUAL_QUICK_W("invokevirtual_quick_w"),
+      ILLEGAL_227, // GETFIELD_QUICK_W("getfield_quick_w"),
+      ILLEGAL_228, // PUTFIELD_QUICK_W("putfield_quick_w"),
+      ILLEGAL_229, // 
+      ILLEGAL_230, // 
+      ILLEGAL_231, // 
+      ILLEGAL_232, // 
+      ILLEGAL_233, // 
+      ILLEGAL_234, // 
+      ILLEGAL_235, // 
+      ILLEGAL_236, // 
+      ILLEGAL_237, // 
+      ILLEGAL_238, // 
+      ILLEGAL_239, //
+      ILLEGAL_240, // 
+      ILLEGAL_241, // 
+      ILLEGAL_242, // 
+      ILLEGAL_243, // 
+      ILLEGAL_244, // 
+      ILLEGAL_245, // 
+      ILLEGAL_246, //
+      ILLEGAL_247, //
+      ILLEGAL_248, //
+      ILLEGAL_249, //
+      ILLEGAL_250, //
+      ILLEGAL_251, //
+      ILLEGAL_252, //
+      ILLEGAL_253, //
+      ILLEGAL_254, // IMPDEP1("impdep1"),
+      ILLEGAL_255, // IMPDEP2("impdep2"),
+      NONE, //
+      COMPOSITE_IF, //
+      COMPOSITE_IF_ELSE, //
+      COMPOSITE_FOR_SUN, //
+      COMPOSITE_FOR_ECLIPSE, //
+      COMPOSITE_ARBITRARY_SCOPE, //
+      COMPOSITE_WHILE, //
+      CLONE, //
+      INCREMENT, //
+      INLINE_ASSIGN, //
+      MULTI_ASSIGN, //
+      FAKEGOTO, //
+      FIELD_ARRAY_ELEMENT_INCREMENT, //
+      FIELD_ARRAY_ELEMENT_ASSIGN, //
+      HEAD, //
+      COMPOSITE_EMPTY_LOOP;
+
+      private Class<?> clazz;
+
+      private ImmediateSpec immediate;
+
+      private PushSpec push;
+
+      private PopSpec pop;
+
+      private Operator operator;
+
+      private ByteCode(Class<?> _class, ImmediateSpec _immediate, PopSpec _pop, PushSpec _push, Operator _operator) {
+         clazz = _class;
+         immediate = _immediate;
+         push = _push;
+         pop = _pop;
+         operator = _operator;
+
+         //    clazz = ByteCode.class.forName("com.amd.javalabs.classparser.InstructionSet$I_"+getName().toUpperCase(), true, ByteCode.class.getClassLoader());
+
+      }
+
+      private ByteCode(Class<?> _class, ImmediateSpec _immediate) {
+         this(_class, _immediate, PopSpec.NONE, PushSpec.NONE, Operator.NONE);
+      }
+
+      private ByteCode(Class<?> _class, PushSpec _push) {
+         this(_class, ImmediateSpec.NONE, PopSpec.NONE, _push, Operator.NONE);
+      }
+
+      private ByteCode(Class<?> _class, ImmediateSpec _immediate, PopSpec _pop) {
+         this(_class, _immediate, _pop, PushSpec.NONE, Operator.NONE);
+      }
+
+      private ByteCode(Class<?> _class, ImmediateSpec _immediate, PopSpec _pop, Operator _operator) {
+         this(_class, _immediate, _pop, PushSpec.NONE, _operator);
+      }
+
+      private ByteCode(Class<?> _class, ImmediateSpec _immediate, PushSpec _push) {
+         this(_class, _immediate, PopSpec.NONE, _push, Operator.NONE);
+      }
+
+      private ByteCode(Class<?> _class, PopSpec _pop, PushSpec _push) {
+         this(_class, ImmediateSpec.NONE, _pop, _push, Operator.NONE);
+      }
+
+      private ByteCode(Class<?> _class, PopSpec _pop, PushSpec _push, Operator _operator) {
+         this(_class, ImmediateSpec.NONE, _pop, _push, _operator);
+      }
+
+      private ByteCode(Class<?> _class, PopSpec _pop) {
+         this(_class, ImmediateSpec.NONE, _pop, PushSpec.NONE, Operator.NONE);
+      }
+
+      private ByteCode() {
+         this(null, ImmediateSpec.NONE, PopSpec.NONE, PushSpec.NONE, Operator.NONE);
+      }
+
+      int getCode() {
+         return (ordinal());
+      }
+
+      String getName() {
+         return (name().toLowerCase());
+      }
+
+      ImmediateSpec getImmediate() {
+         return (immediate);
+      }
+
+      static ByteCode get(int _idx) {
+         return (values()[_idx]);
+      }
+
+      PushSpec getPush() {
+         return (push);
+      }
+
+      PopSpec getPop() {
+         return (pop);
+      }
+
+      // Note I am intentionally skipping PushSpec.LorD.
+      boolean usesDouble() {
+         PushSpec push = getPush();
+         PopSpec pop = getPop();
+         if ((push == PushSpec.D) || (pop == PopSpec.D) || (pop == PopSpec.DD) || (pop == PopSpec.AID)) {
+            return true;
+         }
+         return false;
+      }
+
+      Instruction newInstruction(MethodModel _methodModel, ByteReader byteReader) {
+         Instruction newInstruction = null;
+         if (clazz != null) {
+
+            try {
+
+               Constructor<?> constructor = clazz.getDeclaredConstructor(MethodModel.class, ByteReader.class);
+               newInstruction = (Instruction) constructor.newInstance(_methodModel, byteReader);
+               newInstruction.setLength(byteReader.getOffset() - newInstruction.getThisPC());
+            } catch (SecurityException e) {
+               // TODO Auto-generated catch block
+               e.printStackTrace();
+            } catch (NoSuchMethodException e) {
+               // TODO Auto-generated catch block
+               e.printStackTrace();
+            } catch (IllegalArgumentException e) {
+               // TODO Auto-generated catch block
+               e.printStackTrace();
+            } catch (InstantiationException e) {
+               // TODO Auto-generated catch block
+               e.printStackTrace();
+            } catch (IllegalAccessException e) {
+               // TODO Auto-generated catch block
+               e.printStackTrace();
+            } catch (InvocationTargetException e) {
+               // TODO Auto-generated catch block
+               e.printStackTrace();
+            }
+
+         }
+         return (newInstruction);
+      }
+
+      static Instruction create(MethodModel _methodModel, ByteReader _byteReader) {
+         ByteCode byteCode = get(_byteReader.u1());
+         Instruction newInstruction = byteCode.newInstruction(_methodModel, _byteReader);
+
+         return (newInstruction);
+
+      }
+
+      Operator getOperator() {
+         return (operator);
+      }
+   }
+
+   static class CompositeInstruction extends Instruction{
+
+      protected BranchSet branchSet;
+
+      protected CompositeInstruction(MethodModel method, ByteCode _byteCode, Instruction _firstChild, Instruction _lastChild,
+            BranchSet _branchSet) {
+         super(method, _byteCode, -1);
+         branchSet = _branchSet;
+         setChildren(_firstChild, _lastChild);
+      }
+
+      @Override String getDescription() {
+         return ("COMPOSITE! " + getByteCode());
+      }
+
+      @Override int getThisPC() {
+         return (getLastChild().getThisPC());
+      }
+
+      @Override int getStartPC() {
+         return (getFirstChild().getStartPC());
+      }
+
+      static CompositeInstruction create(ByteCode _byteCode, MethodModel _methodModel, Instruction _firstChild,
+            Instruction _lastChild, BranchSet _branchSet) {
+         CompositeInstruction compositeInstruction = null;
+         switch (_byteCode) {
+            case COMPOSITE_IF:
+               compositeInstruction = new CompositeIfInstruction(_methodModel, _firstChild, _lastChild, _branchSet);
+               break;
+            case COMPOSITE_IF_ELSE:
+               compositeInstruction = new CompositeIfElseInstruction(_methodModel, _firstChild, _lastChild, _branchSet);
+               break;
+            case COMPOSITE_FOR_SUN:
+               compositeInstruction = new CompositeForSunInstruction(_methodModel, _firstChild, _lastChild, _branchSet);
+               break;
+            case COMPOSITE_WHILE:
+               compositeInstruction = new CompositeWhileInstruction(_methodModel, _firstChild, _lastChild, _branchSet);
+               break;
+            case COMPOSITE_FOR_ECLIPSE:
+               compositeInstruction = new CompositeForEclipseInstruction(_methodModel, _firstChild, _lastChild, _branchSet);
+               break;
+            case COMPOSITE_ARBITRARY_SCOPE:
+               compositeInstruction = new CompositeArbitraryScopeInstruction(_methodModel, _firstChild, _lastChild, _branchSet);
+               break;
+            case COMPOSITE_EMPTY_LOOP:
+               compositeInstruction = new CompositeEmptyLoopInstruction(_methodModel, _firstChild, _lastChild, _branchSet);
+               break;
+         }
+         return (compositeInstruction);
+
+      }
+
+      BranchSet getBranchSet() {
+         return (branchSet);
+      }
+   }
+
+   static class CompositeIfInstruction extends CompositeInstruction{
+
+      protected CompositeIfInstruction(MethodModel method, Instruction _firstChild, Instruction _lastChild, BranchSet _branchSet) {
+         super(method, ByteCode.COMPOSITE_IF, _firstChild, _lastChild, _branchSet);
+
+      }
+   }
+
+   static class CompositeIfElseInstruction extends CompositeInstruction{
+
+      protected CompositeIfElseInstruction(MethodModel method, Instruction _firstChild, Instruction _lastChild, BranchSet _branchSet) {
+         super(method, ByteCode.COMPOSITE_IF_ELSE, _firstChild, _lastChild, _branchSet);
+
+      }
+
+   }
+
+   static class CompositeForSunInstruction extends CompositeInstruction{
+
+      protected CompositeForSunInstruction(MethodModel method, Instruction _firstChild, Instruction _lastChild, BranchSet _branchSet) {
+         super(method, ByteCode.COMPOSITE_FOR_SUN, _firstChild, _lastChild, _branchSet);
+
+      }
+   }
+
+   static class CompositeWhileInstruction extends CompositeInstruction{
+
+      protected CompositeWhileInstruction(MethodModel method, Instruction _firstChild, Instruction _lastChild, BranchSet _branchSet) {
+         super(method, ByteCode.COMPOSITE_WHILE, _firstChild, _lastChild, _branchSet);
+
+      }
+   }
+
+   static class CompositeEmptyLoopInstruction extends CompositeInstruction{
+
+      protected CompositeEmptyLoopInstruction(MethodModel method, Instruction _firstChild, Instruction _lastChild,
+            BranchSet _branchSet) {
+         super(method, ByteCode.COMPOSITE_EMPTY_LOOP, _firstChild, _lastChild, _branchSet);
+
+      }
+   }
+
+   static class CompositeForEclipseInstruction extends CompositeInstruction{
+
+      protected CompositeForEclipseInstruction(MethodModel method, Instruction _firstChild, Instruction _lastChild,
+            BranchSet _branchSet) {
+         super(method, ByteCode.COMPOSITE_FOR_ECLIPSE, _firstChild, _lastChild, _branchSet);
+
+      }
+   }
+
+   static class CompositeArbitraryScopeInstruction extends CompositeInstruction{
+
+      protected CompositeArbitraryScopeInstruction(MethodModel method, Instruction _firstChild, Instruction _lastChild,
+            BranchSet _branchSet) {
+         super(method, ByteCode.COMPOSITE_ARBITRARY_SCOPE, _firstChild, _lastChild, _branchSet);
+
+      }
+   }
+
+   static abstract class OperatorInstruction extends Instruction{
+
+      protected OperatorInstruction(MethodModel _methodPoolEntry, ByteCode code, ByteReader reader) {
+         super(_methodPoolEntry, code, reader);
+
+      }
+
+      public Operator getOperator() {
+         return (getByteCode().getOperator());
+      }
+
+   }
+
+   static abstract class BinaryOperator extends OperatorInstruction implements Binary{
+
+      @Override public final Instruction getLhs() {
+         return (getFirstChild());
+      }
+
+      @Override public final Instruction getRhs() {
+         return (getLastChild());
+      }
+
+      protected BinaryOperator(MethodModel _methodPoolEntry, ByteCode code, ByteReader reader) {
+         super(_methodPoolEntry, code, reader);
+      }
+
+   }
+
+   static abstract class UnaryOperator extends OperatorInstruction implements Unary{
+
+      @Override public final Instruction getUnary() {
+         return (getFirstChild());
+      }
+
+      protected UnaryOperator(MethodModel _methodPoolEntry, ByteCode code, ByteReader reader) {
+         super(_methodPoolEntry, code, reader);
+      }
+
+   }
+
+   static abstract class CastOperator extends UnaryOperator{
+
+      protected CastOperator(MethodModel _methodPoolEntry, ByteCode code, ByteReader reader) {
+         super(_methodPoolEntry, code, reader);
+      }
+
+   }
+
+   static abstract class Branch extends Instruction{
+      protected int offset;
+
+      protected boolean breakOrContinue;
+
+      protected Instruction target;
+
+      int getAbsolute() {
+         return (getThisPC() + getOffset());
+      }
+
+      private int getOffset() {
+         return (offset);
+      }
+
+      Branch(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+
+      }
+
+      Branch(MethodModel _methodPoolEntry, ByteCode _byteCode, Instruction _target) {
+         super(_methodPoolEntry, _byteCode, -1);
+         setTarget(_target);
+
+      }
+
+      Instruction getTarget() {
+         return (target);
+      }
+
+      void setTarget(Instruction _target) {
+         target = _target;
+         offset = target.getThisPC() - getThisPC();
+         target.addBranchTarget(this);
+      }
+
+      boolean isConditional() {
+         return (this instanceof ConditionalBranch);
+      }
+
+      boolean isUnconditional() {
+         return (this instanceof UnconditionalBranch);
+      }
+
+      boolean isReverseConditional() {
+         return (isConditional() && isReverse());
+      }
+
+      boolean isForwardConditional() {
+         return (isConditional() && isForward());
+      }
+
+      boolean isReverseUnconditional() {
+         return (isUnconditional() && isReverse());
+      }
+
+      boolean isForwardUnconditional() {
+         return (isUnconditional() && isForward());
+      }
+
+      boolean isReverse() {
+         return (offset < 0);
+      }
+
+      boolean isForward() {
+         return (offset >= 0);
+      }
+
+      void unhook() {
+         getTarget().removeBranchTarget(this);
+
+      }
+
+      void setBreakOrContinue(boolean b) {
+         breakOrContinue = true;
+
+      }
+
+      boolean isBreakOrContinue() {
+         return (breakOrContinue);
+
+      }
+
+      public void retarget(Instruction _newTarget) {
+         System.out.println("retargetting " + pc + " -> " + target.getThisPC() + " to " + _newTarget.getThisPC());
+         unhook(); // removes this from the list of branchers to target
+         setTarget(_newTarget);
+         System.out.println("retargetted " + pc + " -> " + target.getThisPC());
+         //  _newTarget.addBranchTarget(this);
+      }
+
+   }
+
+   static abstract class ConditionalBranch extends Branch{
+      private BranchSet branchSet;
+
+      ConditionalBranch(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+      }
+
+      void setBranchSet(BranchSet _branchSet) {
+         branchSet = _branchSet;
+      }
+
+      BranchSet getOrCreateBranchSet() {
+         if (branchSet == null) {
+            branchSet = new BranchSet(this);
+         }
+         return branchSet;
+      }
+
+      BranchSet getBranchSet() {
+         return branchSet;
+      }
+
+      // extent is a guess but we know that the target will be beyond extent, we are not interested in targets that fall before extent
+      ConditionalBranch findEndOfConditionalBranchSet(Instruction _extent) {
+         // bummer ;)
+         // we need to find the actual branch set.  Be careful here we can only create a branch set when we *know* that a conditional is the last in the set. 
+         // we don't know that here.  We have to scan forward to try to find it 
+         ConditionalBranch i = this;
+         Instruction theTarget = null;
+         ConditionalBranch lastToTarget = null;
+
+         if (getTarget().isAfter(_extent)) {
+            // if this conditional is already pointing beyond extent then we know the target
+            theTarget = getTarget();
+            lastToTarget = this;
+         }
+         while (i.getNextExpr().isBranch() && i.getNextExpr().asBranch().isForwardConditional()) {
+            Branch nextBranch = i.getNextExpr().asBranch();
+            if (theTarget == null && nextBranch.getTarget().isAfter(_extent)) {
+               theTarget = nextBranch.getTarget();
+               lastToTarget = this;
+            } else if (nextBranch.getTarget() == theTarget) {
+               lastToTarget = this;
+            }
+            i = (ConditionalBranch) i.getNextExpr();
+
+         }
+         if (theTarget == null) {
+            throw new IllegalStateException("unable to find end of while extent");
+         }
+         return (lastToTarget);
+      }
+   }
+
+   static abstract class UnconditionalBranch extends Branch{
+
+      UnconditionalBranch(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+      }
+
+      UnconditionalBranch(MethodModel _methodPoolEntry, ByteCode _byteCode, Instruction _target) {
+         super(_methodPoolEntry, _byteCode, _target);
+      }
+
+   }
+
+   static abstract class IfUnary extends ConditionalBranch16 implements Unary{
+
+      IfUnary(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+
+      }
+
+      @Override public Instruction getUnary() {
+         return (getFirstChild());
+      }
+
+   }
+
+   static abstract class If extends ConditionalBranch16 implements Binary{
+
+      If(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+
+      }
+
+      @Override public final Instruction getLhs() {
+         return (getFirstChild());
+      }
+
+      @Override public final Instruction getRhs() {
+         return (getLastChild());
+      }
+
+   }
+
+   static abstract class ConditionalBranch16 extends ConditionalBranch implements HasOperator{
+
+      ConditionalBranch16(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+         offset = _byteReader.s2();
+
+      }
+
+      @Override public Operator getOperator() {
+         return (getByteCode().getOperator());
+      }
+   }
+
+   static abstract class UnconditionalBranch16 extends UnconditionalBranch{
+
+      UnconditionalBranch16(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+         offset = _byteReader.s2();
+
+      }
+
+   }
+
+   static abstract class Branch32 extends UnconditionalBranch{
+      Branch32(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+         offset = _byteReader.s4();
+
+      }
+
+   }
+
+   static abstract class ArrayAccess extends Instruction{
+
+      protected ArrayAccess(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+
+      }
+
+      Instruction getArrayRef() {
+         return (getFirstChild());
+      }
+
+      Instruction getArrayIndex() {
+         return (getFirstChild().getNextExpr());
+      }
+
+   }
+
+   static abstract class AccessArrayElement extends ArrayAccess{
+      protected AccessArrayElement(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+      }
+   }
+
+   static class I_AALOAD extends AccessArrayElement{
+      I_AALOAD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.AALOAD, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push reference from arrayref and index");
+      }
+
+   }
+
+   static abstract class AssignToArrayElement extends ArrayAccess{
+
+      public Instruction getValue() {
+         return (getFirstChild().getNextExpr().getNextExpr());
+      }
+
+      protected AssignToArrayElement(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+
+      }
+
+   }
+
+   static class I_AASTORE extends AssignToArrayElement{
+      I_AASTORE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.AASTORE, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop reference into arrayref[index]");
+      }
+
+   }
+
+   static class I_ACONST_NULL extends Instruction implements Constant<Object>{
+      I_ACONST_NULL(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ACONST_NULL, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push null");
+      }
+
+      @Override public Object getValue() {
+         return null;
+      }
+
+   }
+
+   static abstract class LocalVariableConstIndexAccessor extends IndexConst implements AccessLocalVariable{
+      LocalVariableConstIndexAccessor(MethodModel methodPoolEntry, ByteCode byteCode, ByteReader byteReader, int index) {
+         super(methodPoolEntry, byteCode, byteReader, index);
+      }
+
+      @Override public final int getLocalVariableTableIndex() {
+         return (index);
+      }
+
+      @Override public final LocalVariableInfo getLocalVariableInfo() {
+         return (method.getLocalVariableTableEntry().getVariable(getThisPC() + getLength(), getLocalVariableTableIndex()));
+      }
+   }
+
+   static abstract class LocalVariableConstIndexLoad extends LocalVariableConstIndexAccessor{
+      LocalVariableConstIndexLoad(MethodModel methodPoolEntry, ByteCode byteCode, ByteReader byteReader, int index) {
+         super(methodPoolEntry, byteCode, byteReader, index);
+      }
+
+      @Override final String getDescription() {
+         return ("push reference from local var index " + index);
+      }
+
+   }
+
+   static abstract class LocalVariableConstIndexStore extends LocalVariableConstIndexAccessor implements AssignToLocalVariable{
+      LocalVariableConstIndexStore(MethodModel methodPoolEntry, ByteCode byteCode, ByteReader byteReader, int index) {
+         super(methodPoolEntry, byteCode, byteReader, index);
+      }
+
+      @Override public boolean isDeclaration() {
+         return (method.getLocalVariableTableEntry().getVariable(getThisPC() + getLength(), getLocalVariableTableIndex())
+               .getStart() == getThisPC() + getLength());
+      }
+
+      @Override final String getDescription() {
+         return ("pop reference into local var index " + index);
+      }
+   }
+
+   static abstract class LocalVariableIndex08Accessor extends Index08 implements AccessLocalVariable{
+      LocalVariableIndex08Accessor(MethodModel methodPoolEntry, ByteCode byteCode, ByteReader byteReader) {
+         super(methodPoolEntry, byteCode, byteReader);
+      }
+
+      @Override public final int getLocalVariableTableIndex() {
+         return (index);
+      }
+
+      @Override public final LocalVariableInfo getLocalVariableInfo() {
+         return (method.getLocalVariableTableEntry().getVariable(getThisPC() + getLength(), getLocalVariableTableIndex()));
+      }
+   }
+
+   static abstract class LocalVariableIndex08Load extends LocalVariableIndex08Accessor{
+      LocalVariableIndex08Load(MethodModel methodPoolEntry, ByteCode byteCode, ByteReader byteReader) {
+         super(methodPoolEntry, byteCode, byteReader);
+      }
+
+      @Override final String getDescription() {
+         return ("push reference from local var index " + index);
+      }
+
+   }
+
+   static abstract class LocalVariableIndex08Store extends LocalVariableIndex08Accessor implements AssignToLocalVariable{
+      LocalVariableIndex08Store(MethodModel methodPoolEntry, ByteCode byteCode, ByteReader byteReader) {
+         super(methodPoolEntry, byteCode, byteReader);
+      }
+
+      @Override public boolean isDeclaration() {
+         LocalVariableTableEntry localVariableTableEntry = method.getLocalVariableTableEntry();
+         LocalVariableInfo localVarInfo = localVariableTableEntry.getVariable(getThisPC() + getLength(),
+               getLocalVariableTableIndex());
+         return (localVarInfo != null && localVarInfo.getStart() == getThisPC() + getLength());
+      }
+
+      @Override final String getDescription() {
+         return ("pop reference into local var index " + index);
+      }
+
+   }
+
+   static class I_ALOAD extends LocalVariableIndex08Load{
+      I_ALOAD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ALOAD, _byteReader);
+
+      }
+
+   }
+
+   static class I_ALOAD_0 extends LocalVariableConstIndexLoad{
+      I_ALOAD_0(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ALOAD_0, _byteReader, 0);
+      }
+   }
+
+   static class I_ALOAD_1 extends LocalVariableConstIndexLoad{
+      I_ALOAD_1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ALOAD_1, _byteReader, 1);
+
+      }
+
+   }
+
+   static class I_ALOAD_2 extends LocalVariableConstIndexLoad{
+      I_ALOAD_2(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ALOAD_2, _byteReader, 2);
+      }
+   }
+
+   static class I_ALOAD_3 extends LocalVariableConstIndexLoad{
+      I_ALOAD_3(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ALOAD_3, _byteReader, 3);
+      }
+   }
+
+   static class I_ANEWARRAY extends Index16 implements New{
+
+      I_ANEWARRAY(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ANEWARRAY, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("new array of reference");
+      }
+
+   }
+
+   static class I_ARETURN extends Return{
+      I_ARETURN(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ARETURN, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("return popped reference");
+      }
+
+   }
+
+   static class I_ARRAYLENGTH extends Instruction{
+      I_ARRAYLENGTH(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ARRAYLENGTH, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop array push length");
+      }
+   }
+
+   static class I_ASTORE extends LocalVariableIndex08Store{
+      I_ASTORE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ASTORE, _byteReader);
+
+      }
+
+   }
+
+   static class I_ASTORE_0 extends LocalVariableConstIndexStore{
+      I_ASTORE_0(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ASTORE_0, _byteReader, 0);
+
+      }
+
+   }
+
+   static class I_ASTORE_1 extends LocalVariableConstIndexStore{
+      I_ASTORE_1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ASTORE_1, _byteReader, 1);
+
+      }
+
+   }
+
+   static class I_ASTORE_2 extends LocalVariableConstIndexStore{
+      I_ASTORE_2(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ASTORE_2, _byteReader, 2);
+
+      }
+
+   }
+
+   static class I_ASTORE_3 extends LocalVariableConstIndexStore{
+      I_ASTORE_3(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ASTORE_3, _byteReader, 3);
+
+      }
+
+   }
+
+   static class I_ATHROW extends Instruction{
+      I_ATHROW(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ATHROW, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop reference and throw");
+      }
+
+   }
+
+   static class I_BALOAD extends AccessArrayElement{
+      I_BALOAD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.BALOAD, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push byte/boolean from arrayref and index");
+      }
+
+   }
+
+   static class I_BASTORE extends AssignToArrayElement{
+      I_BASTORE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.BASTORE, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop boolean/byte into arrayref[index]");
+      }
+
+   }
+
+   static class I_BIPUSH extends ImmediateConstant<Integer>{
+
+      I_BIPUSH(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.BIPUSH, _byteReader);
+         value = _byteReader.u1();
+
+      }
+
+      @Override String getDescription() {
+         return ("push (byte)");
+      }
+
+      @Override public Integer getValue() {
+         int byteValue = super.getValue();
+         if (byteValue > 127) {
+            byteValue = -(256 - byteValue);
+         }
+         return (byteValue);
+      }
+   }
+
+   static class I_CALOAD extends AccessArrayElement{
+      I_CALOAD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.CALOAD, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push char from arrayref and index");
+      }
+
+   }
+
+   static class I_CASTORE extends AssignToArrayElement{
+      I_CASTORE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.CASTORE, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop char into arrayref[index]");
+      }
+   }
+
+   static class I_CHECKCAST extends Index16{
+      I_CHECKCAST(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.CHECKCAST, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("peek reference check against the constant accessed 16 bit");
+      }
+
+   }
+
+   static class I_D2F extends CastOperator{
+      I_D2F(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.D2F, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop double push float");
+      }
+
+   }
+
+   static class I_D2I extends CastOperator{
+      I_D2I(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.D2I, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop double push int");
+      }
+
+   }
+
+   static class I_D2L extends CastOperator{
+      I_D2L(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.D2L, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop double push long");
+      }
+
+   }
+
+   static class I_DADD extends BinaryOperator{
+      I_DADD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DADD, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("add top two doubles");
+      }
+
+   }
+
+   static class I_DALOAD extends AccessArrayElement{
+      I_DALOAD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DALOAD, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push double from arrayref and index");
+      }
+
+   }
+
+   static class I_DASTORE extends AssignToArrayElement{
+      I_DASTORE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DASTORE, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop double into arrayref[index]");
+      }
+
+   }
+
+   static class I_DCMPG extends Instruction{
+      I_DCMPG(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DCMPG, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push result of double comparison");
+      }
+
+   }
+
+   static class I_DCMPL extends Instruction{
+      I_DCMPL(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DCMPL, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push result of double comparison");
+      }
+
+   }
+
+   static abstract class BytecodeEncodedConstant<T> extends Instruction implements Constant<T>{
+      private T value;
+
+      BytecodeEncodedConstant(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader, T _value) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+         value = _value;
+
+      }
+
+      @Override public T getValue() {
+         return (value);
+      }
+
+   }
+
+   static abstract class ImmediateConstant<T> extends Instruction implements Constant<T>{
+      protected T value;
+
+      ImmediateConstant(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+
+      }
+
+      @Override public T getValue() {
+         return (value);
+      }
+
+   }
+
+   static class I_DCONST_0 extends BytecodeEncodedConstant<Double>{
+      I_DCONST_0(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DCONST_0, _byteReader, 0.0);
+
+      }
+
+      @Override String getDescription() {
+         return ("push (double) 0.0");
+      }
+
+   }
+
+   static class I_DCONST_1 extends BytecodeEncodedConstant<Double>{
+      I_DCONST_1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DCONST_1, _byteReader, 1.0);
+
+      }
+
+      @Override String getDescription() {
+         return ("push (double) 1.0");
+      }
+
+   }
+
+   static class I_DDIV extends BinaryOperator{
+      I_DDIV(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DDIV, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("div top two doubles");
+      }
+
+   }
+
+   static class I_DLOAD extends LocalVariableIndex08Load{
+      I_DLOAD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DLOAD, _byteReader);
+
+      }
+
+   }
+
+   static class I_DLOAD_0 extends LocalVariableConstIndexLoad{
+      I_DLOAD_0(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DLOAD_0, _byteReader, 0);
+
+      }
+
+   }
+
+   static class I_DLOAD_1 extends LocalVariableConstIndexLoad{
+      I_DLOAD_1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DLOAD_1, _byteReader, 1);
+
+      }
+
+   }
+
+   static class I_DLOAD_2 extends LocalVariableConstIndexLoad{
+      I_DLOAD_2(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DLOAD_2, _byteReader, 2);
+
+      }
+
+   }
+
+   static class I_DLOAD_3 extends LocalVariableConstIndexLoad{
+      I_DLOAD_3(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DLOAD_3, _byteReader, 3);
+
+      }
+
+   }
+
+   static class I_DMUL extends BinaryOperator{
+      I_DMUL(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DMUL, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("mul top two doubles");
+      }
+
+   }
+
+   static class I_DNEG extends UnaryOperator{
+      I_DNEG(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DNEG, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("neg top double");
+      }
+
+   }
+
+   static class I_DREM extends BinaryOperator{
+      I_DREM(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DREM, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("rem top two doubles");
+      }
+
+   }
+
+   static class I_DRETURN extends Return{
+      I_DRETURN(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DRETURN, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("return popped double");
+      }
+
+   }
+
+   static class I_DSTORE extends LocalVariableIndex08Store{
+      I_DSTORE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DSTORE, _byteReader);
+
+      }
+
+   }
+
+   static class I_DSTORE_0 extends LocalVariableConstIndexStore{
+      I_DSTORE_0(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DSTORE_0, _byteReader, 0);
+
+      }
+
+   }
+
+   static class I_DSTORE_1 extends LocalVariableConstIndexStore{
+      I_DSTORE_1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DSTORE_1, _byteReader, 1);
+
+      }
+
+   }
+
+   static class I_DSTORE_2 extends LocalVariableConstIndexStore{
+      I_DSTORE_2(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DSTORE_2, _byteReader, 2);
+
+      }
+
+   }
+
+   static class I_DSTORE_3 extends LocalVariableConstIndexStore{
+      I_DSTORE_3(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DSTORE_3, _byteReader, 3);
+
+      }
+
+   }
+
+   static class I_DSUB extends BinaryOperator{
+      I_DSUB(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DSUB, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("sub top two doubles");
+      }
+
+   }
+
+   static abstract class DUP extends Instruction{
+      DUP(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+
+      }
+   }
+
+   static class I_DUP extends DUP{
+      I_DUP(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DUP, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("dup top item");
+      }
+
+   }
+
+   static class I_DUP_X1 extends DUP{
+      I_DUP_X1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DUP_X1, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("dup top item 2 items down");
+      }
+
+   }
+
+   static class I_DUP_X2 extends DUP{
+      I_DUP_X2(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DUP_X2, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("dup top item 3 items down");
+      }
+
+   }
+
+   static class I_DUP2 extends DUP{
+      I_DUP2(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DUP2, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("dup top 2 items");
+      }
+
+   }
+
+   static class I_DUP2_X1 extends DUP{
+      I_DUP2_X1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DUP2_X1, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("dup top 2 items 2 items down");
+      }
+
+   }
+
+   static class I_DUP2_X2 extends DUP{
+      I_DUP2_X2(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.DUP_X2, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("dup top 2 items 3 items down");
+      }
+
+   }
+
+   static class I_F2D extends CastOperator{
+      I_F2D(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.F2D, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop float push double");
+      }
+
+   }
+
+   static class I_F2I extends CastOperator{
+      I_F2I(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.F2I, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop float push int");
+      }
+
+   }
+
+   static class I_F2L extends CastOperator{
+      I_F2L(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.F2L, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop float push long");
+      }
+
+   }
+
+   static class I_FADD extends BinaryOperator{
+      I_FADD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FADD, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("add top two floats");
+      }
+
+   }
+
+   static class I_FALOAD extends AccessArrayElement{
+      I_FALOAD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FALOAD, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push float from arrayref and index");
+      }
+
+   }
+
+   static class I_FASTORE extends AssignToArrayElement{
+      I_FASTORE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FASTORE, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop float into arrayref[index]");
+      }
+
+   }
+
+   static class I_FCMPG extends BinaryOperator{
+      I_FCMPG(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FCMPG, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push result of float comparison");
+      }
+
+   }
+
+   static class I_FCMPL extends BinaryOperator{
+      I_FCMPL(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FCMPL, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push result of float comparison");
+      }
+
+   }
+
+   static class I_FCONST_0 extends BytecodeEncodedConstant<Float>{
+      I_FCONST_0(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FCONST_0, _byteReader, 0f);
+
+      }
+
+      @Override String getDescription() {
+         return ("push (float) 0.0");
+      }
+
+   }
+
+   static class I_FCONST_1 extends BytecodeEncodedConstant<Float>{
+      I_FCONST_1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FCONST_1, _byteReader, 1f);
+
+      }
+
+      @Override String getDescription() {
+         return ("push (float) 1.0");
+      }
+
+   }
+
+   static class I_FCONST_2 extends BytecodeEncodedConstant<Float>{
+      I_FCONST_2(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FCONST_2, _byteReader, 2f);
+
+      }
+
+      @Override String getDescription() {
+         return ("push (float) 2.0");
+      }
+
+   }
+
+   static class I_FDIV extends BinaryOperator{
+      I_FDIV(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FDIV, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("div top two floats");
+      }
+
+   }
+
+   static class I_FLOAD extends LocalVariableIndex08Load{
+      I_FLOAD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FLOAD, _byteReader);
+
+      }
+
+   }
+
+   static class I_FLOAD_0 extends LocalVariableConstIndexLoad{
+      I_FLOAD_0(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FLOAD_0, _byteReader, 0);
+
+      }
+
+   }
+
+   static class I_FLOAD_1 extends LocalVariableConstIndexLoad{
+      I_FLOAD_1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FLOAD_1, _byteReader, 1);
+
+      }
+
+   }
+
+   static class I_FLOAD_2 extends LocalVariableConstIndexLoad{
+      I_FLOAD_2(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FLOAD_2, _byteReader, 2);
+
+      }
+
+   }
+
+   static class I_FLOAD_3 extends LocalVariableConstIndexLoad{
+      I_FLOAD_3(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FLOAD_3, _byteReader, 3);
+
+      }
+
+   }
+
+   static class I_FMUL extends BinaryOperator{
+      I_FMUL(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FMUL, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("mul top two floats");
+      }
+
+   }
+
+   static class I_FNEG extends UnaryOperator{
+      I_FNEG(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FNEG, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("neg top float");
+      }
+
+   }
+
+   static class I_FREM extends BinaryOperator{
+      I_FREM(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FREM, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("rem top two floats");
+      }
+
+   }
+
+   static class I_FRETURN extends Return{
+      I_FRETURN(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FRETURN, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("return popped float");
+      }
+
+   }
+
+   static class I_FSTORE extends LocalVariableIndex08Store{
+      I_FSTORE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FSTORE, _byteReader);
+
+      }
+
+   }
+
+   static class I_FSTORE_0 extends LocalVariableConstIndexStore{
+      I_FSTORE_0(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FSTORE_0, _byteReader, 0);
+
+      }
+
+   }
+
+   static class I_FSTORE_1 extends LocalVariableConstIndexStore{
+      I_FSTORE_1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FSTORE_1, _byteReader, 1);
+
+      }
+
+   }
+
+   static class I_FSTORE_2 extends LocalVariableConstIndexStore{
+      I_FSTORE_2(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FSTORE_2, _byteReader, 2);
+
+      }
+
+   }
+
+   static class I_FSTORE_3 extends LocalVariableConstIndexStore{
+      I_FSTORE_3(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FSTORE_3, _byteReader, 3);
+
+      }
+
+   }
+
+   static class I_FSUB extends BinaryOperator{
+      I_FSUB(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.FSUB, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("sub top two floats");
+      }
+
+   }
+
+   static class I_GETFIELD extends Index16 implements AccessInstanceField{
+      I_GETFIELD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.GETFIELD, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push value from field referenced by 16 bit constant index");
+      }
+
+      @Override public int getConstantPoolFieldIndex() {
+         return (index);
+      }
+
+      @Override public FieldEntry getConstantPoolFieldEntry() {
+         return (method.getConstantPool().getFieldEntry(getConstantPoolFieldIndex()));
+      }
+
+      @Override public Instruction getInstance() {
+         return (getFirstChild());
+      }
+
+      @Override int getStackConsumeCount() {
+         return (1);
+      }
+
+      @Override int getStackProduceCount() {
+         return (1);
+      }
+
+   }
+
+   static class I_GETSTATIC extends Index16 implements AccessField{
+      I_GETSTATIC(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.GETSTATIC, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push  static field value at 16 bit constant index");
+      }
+
+      @Override public int getConstantPoolFieldIndex() {
+         return (index);
+      }
+
+      @Override public FieldEntry getConstantPoolFieldEntry() {
+         return (method.getConstantPool().getFieldEntry(getConstantPoolFieldIndex()));
+      }
+
+      @Override int getStackConsumeCount() {
+         return (0);
+      }
+
+      @Override int getStackProduceCount() {
+         return (1);
+      }
+   }
+
+   static class I_GOTO extends UnconditionalBranch16{
+      I_GOTO(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.GOTO, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch ");
+      }
+
+   }
+
+   static class I_GOTO_W extends Branch32{
+      I_GOTO_W(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.GOTO_W, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("goto wide branch");
+      }
+
+   }
+
+   static class I_I2B extends CastOperator{
+      I_I2B(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.I2B, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop int push byte");
+      }
+
+   }
+
+   static class I_I2C extends CastOperator{
+      I_I2C(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.I2C, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop int push char");
+      }
+
+   }
+
+   static class I_I2D extends CastOperator{
+      I_I2D(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.I2D, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop int push double");
+      }
+
+   }
+
+   static class I_I2F extends CastOperator{
+      I_I2F(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.I2F, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop int push float");
+      }
+
+   }
+
+   static class I_I2L extends CastOperator{
+      I_I2L(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.I2L, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop int push long");
+      }
+
+   }
+
+   static class I_I2S extends CastOperator{
+      I_I2S(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.I2S, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop int push short");
+      }
+
+   }
+
+   static class I_IADD extends BinaryOperator{
+      I_IADD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IADD, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("add top two ints");
+      }
+
+   }
+
+   static class I_IALOAD extends AccessArrayElement{
+      I_IALOAD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IALOAD, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push int from arrayref and index");
+      }
+
+   }
+
+   static class I_IAND extends BinaryOperator{
+      I_IAND(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IAND, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("and top two ints");
+      }
+
+   }
+
+   static class I_IASTORE extends AssignToArrayElement{
+      I_IASTORE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IASTORE, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop int into arrayref[index]");
+      }
+
+   }
+
+   static class I_ICONST_0 extends BytecodeEncodedConstant<Integer>{
+      I_ICONST_0(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ICONST_0, _byteReader, 0);
+
+      }
+
+      @Override String getDescription() {
+         return ("push (int) 0");
+      }
+
+   }
+
+   static class I_ICONST_1 extends BytecodeEncodedConstant<Integer>{
+      I_ICONST_1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ICONST_1, _byteReader, 1);
+
+      }
+
+      String getDescription() {
+         return ("push (int) 1");
+      }
+
+   }
+
+   static class I_ICONST_2 extends BytecodeEncodedConstant<Integer>{
+      I_ICONST_2(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ICONST_2, _byteReader, 2);
+
+      }
+
+      @Override String getDescription() {
+         return ("push (int) 2");
+      }
+
+   }
+
+   static class I_ICONST_3 extends BytecodeEncodedConstant<Integer>{
+      I_ICONST_3(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ICONST_3, _byteReader, 3);
+
+      }
+
+      @Override String getDescription() {
+         return ("push (int) 3");
+      }
+
+   }
+
+   static class I_ICONST_4 extends BytecodeEncodedConstant<Integer>{
+      I_ICONST_4(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ICONST_4, _byteReader, 4);
+
+      }
+
+      @Override String getDescription() {
+         return ("push (int) 4");
+      }
+
+   }
+
+   static class I_ICONST_5 extends BytecodeEncodedConstant<Integer>{
+      I_ICONST_5(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ICONST_5, _byteReader, 5);
+
+      }
+
+      @Override String getDescription() {
+         return ("push (int) 5");
+      }
+
+   }
+
+   static class I_ICONST_M1 extends BytecodeEncodedConstant<Integer>{
+      I_ICONST_M1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ICONST_M1, _byteReader, -1);
+
+      }
+
+      @Override String getDescription() {
+         return ("push (int)-1");
+      }
+
+   }
+
+   static class I_IDIV extends BinaryOperator{
+      I_IDIV(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IDIV, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("div top two ints");
+      }
+
+   }
+
+   static class I_IF_ACMPEQ extends If{
+      I_IF_ACMPEQ(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IF_ACMPEQ, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch if stack top references ==");
+      }
+
+   }
+
+   static class I_IF_ACMPNE extends If{
+      I_IF_ACMPNE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IF_ACMPNE, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch if stack top references !=");
+      }
+
+   }
+
+   static class I_IF_ICMPEQ extends If{
+      I_IF_ICMPEQ(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IF_ICMPEQ, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch if stack top ints ==");
+      }
+
+   }
+
+   static class I_IF_ICMPGE extends If{
+      I_IF_ICMPGE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IF_ICMPGE, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch if stack top ints >=");
+      }
+
+   }
+
+   static class I_IF_ICMPGT extends If{
+      I_IF_ICMPGT(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IF_ICMPGT, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch if stack top ints > ");
+      }
+
+   }
+
+   static class I_IF_ICMPLE extends If{
+      I_IF_ICMPLE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IF_ICMPLE, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch if stack top ints <=");
+      }
+
+   }
+
+   static class I_IF_ICMPLT extends If{
+      I_IF_ICMPLT(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IF_ICMPLT, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch if stack top ints < ");
+      }
+
+   }
+
+   static class I_IF_ICMPNE extends If{
+      I_IF_ICMPNE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IF_ICMPNE, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch if stack top ints !=");
+      }
+
+   }
+
+   static class I_IFEQ extends IfUnary{
+      I_IFEQ(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IFEQ, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch if stack top int == 0");
+      }
+
+   }
+
+   static class I_IFGE extends IfUnary{
+      I_IFGE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IFGE, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch if stack top int >= 0");
+      }
+
+   }
+
+   static class I_IFGT extends IfUnary{
+      I_IFGT(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IFGT, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch if stack top int > 0");
+      }
+
+   }
+
+   static class I_IFLE extends IfUnary{
+      I_IFLE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IFLE, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch if stack top int <= 0");
+      }
+
+   }
+
+   static class I_IFLT extends IfUnary{
+      I_IFLT(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IFLT, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch if stack top int < 0");
+      }
+
+   }
+
+   static class I_IFNE extends IfUnary{
+      I_IFNE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IFNE, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch if stack top int != 0");
+      }
+
+   }
+
+   static class I_IFNONNULL extends ConditionalBranch16{
+      I_IFNONNULL(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IFNONNULL, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch if non null");
+      }
+
+   }
+
+   static class I_IFNULL extends ConditionalBranch16{
+      I_IFNULL(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IFNULL, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("branch if null");
+      }
+
+   }
+
+   static class I_IINC extends Index08{
+      private int delta;
+
+      I_IINC(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IINC, _byteReader);
+         delta = _byteReader.u1();
+
+      }
+
+      @Override String getDescription() {
+         return ("inc var index 08 bit by byte");
+      }
+
+      LocalVariableInfo getLocalVariableInfo() {
+         return (method.getLocalVariableTableEntry().getVariable(getThisPC(), getLocalVariableTableIndex()));
+      }
+
+      int getLocalVariableTableIndex() {
+         return (index);
+      }
+
+      int getDelta() {
+         return (delta);
+      }
+
+      boolean isInc() {
+         return getAdjust() > 0;
+      }
+
+      int getAdjust() {
+         int adjust = delta;
+         if (adjust > 127) {
+            adjust = -256 + adjust;
+         }
+         return (adjust);
+      }
+   }
+
+   static class I_ILOAD extends LocalVariableIndex08Load{
+      I_ILOAD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ILOAD, _byteReader);
+
+      }
+
+   }
+
+   static class I_ILOAD_0 extends LocalVariableConstIndexLoad{
+      I_ILOAD_0(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ILOAD_0, _byteReader, 0);
+
+      }
+
+   }
+
+   static class I_ILOAD_1 extends LocalVariableConstIndexLoad{
+      I_ILOAD_1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ILOAD_1, _byteReader, 1);
+
+      }
+
+   }
+
+   static class I_ILOAD_2 extends LocalVariableConstIndexLoad{
+      I_ILOAD_2(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ILOAD_2, _byteReader, 2);
+
+      }
+
+   }
+
+   static class I_ILOAD_3 extends LocalVariableConstIndexLoad{
+      I_ILOAD_3(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ILOAD_3, _byteReader, 3);
+
+      }
+
+   }
+
+   static class I_IMUL extends BinaryOperator{
+      I_IMUL(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IMUL, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("mul top two ints");
+      }
+
+   }
+
+   static class I_INEG extends UnaryOperator{
+      I_INEG(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.INEG, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("neg top int");
+      }
+
+   }
+
+   static class I_INSTANCEOF extends Index16{
+      I_INSTANCEOF(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.INSTANCEOF, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop reference check against the constant accessed 16 bit push 1 if same");
+      }
+
+   }
+
+   static class I_INVOKEINTERFACE extends Index16 implements InterfaceConstantPoolMethodIndexAccessor{
+      private int args;
+
+      I_INVOKEINTERFACE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.INVOKEINTERFACE, _byteReader);
+         args = _byteReader.u1();
+         @SuppressWarnings("unused") int zeroByte = _byteReader.u1();
+
+      }
+
+      @Override public int getArgs() {
+         return (args);
+      }
+
+      @Override String getDescription() {
+         return ("pop args and call the interface method referenced by 16 bit constant index");
+      }
+
+      @Override public int getConstantPoolInterfaceMethodIndex() {
+         return (index);
+      }
+
+      @Override public ConstantPool.InterfaceMethodEntry getConstantPoolInterfaceMethodEntry() {
+         return (method.getConstantPool().getInterfaceMethodEntry(getConstantPoolInterfaceMethodIndex()));
+      }
+
+      @Override public Instruction getArg(int _arg) {
+         Instruction child = getFirstChild();
+         _arg++;
+         while (_arg-- != 0) {
+            child = child.getNextExpr();
+         }
+         return (child);
+      }
+
+      @Override public Instruction getInstanceReference() {
+         return (getFirstChild());
+      }
+
+      @Override int getStackConsumeCount() {
+         return (getConstantPoolInterfaceMethodEntry().getStackConsumeCount() + 1); // + 1 to account for instance 'this'
+
+      }
+
+      @Override int getStackProduceCount() {
+         return (getConstantPoolInterfaceMethodEntry().getStackProduceCount()); // + 1 to account for instance 'this'
+      }
+   }
+
+   static class I_INVOKEDYNAMIC extends Index16 implements InterfaceConstantPoolMethodIndexAccessor{
+      private int args;
+
+      I_INVOKEDYNAMIC(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.INVOKEDYNAMIC, _byteReader);
+         args = _byteReader.u1();
+         @SuppressWarnings("unused") int zeroByte = _byteReader.u1();
+
+      }
+
+      @Override public int getArgs() {
+         return (args);
+      }
+
+      @Override String getDescription() {
+         return ("pop args and call the invoke dynamic method referenced by 16 bit constant index");
+      }
+
+      @Override public int getConstantPoolInterfaceMethodIndex() {
+         return (index);
+      }
+
+      @Override public ConstantPool.InterfaceMethodEntry getConstantPoolInterfaceMethodEntry() {
+         return (method.getConstantPool().getInterfaceMethodEntry(getConstantPoolInterfaceMethodIndex()));
+      }
+
+      @Override public Instruction getArg(int _arg) {
+         Instruction child = getFirstChild();
+         _arg++;
+         while (_arg-- != 0) {
+            child = child.getNextExpr();
+         }
+         return (child);
+      }
+
+      @Override public Instruction getInstanceReference() {
+         return (getFirstChild());
+      }
+
+      @Override int getStackConsumeCount() {
+         return (getConstantPoolInterfaceMethodEntry().getStackConsumeCount() + 1); // + 1 to account for instance 'this'
+
+      }
+
+      @Override int getStackProduceCount() {
+         return (getConstantPoolInterfaceMethodEntry().getStackProduceCount()); // + 1 to account for instance 'this'
+      }
+   }
+
+   static class I_INVOKESPECIAL extends Index16 implements VirtualMethodCall{
+
+      I_INVOKESPECIAL(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.INVOKESPECIAL, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop object reference and args and call the special method referenced by 16 bit constant index");
+      }
+
+      @Override public int getConstantPoolMethodIndex() {
+         return (index);
+      }
+
+      @Override public ConstantPool.MethodEntry getConstantPoolMethodEntry() {
+         return (method.getConstantPool().getMethodEntry(getConstantPoolMethodIndex()));
+      }
+
+      @Override public Instruction getArg(int _arg) {
+         Instruction child = getFirstChild();
+         _arg++;
+         while (_arg-- != 0) {
+            child = child.getNextExpr();
+         }
+         return (child);
+      }
+
+      @Override public Instruction getInstanceReference() {
+         return (getFirstChild());
+      }
+
+      @Override public int getStackConsumeCount() {
+         return (getConstantPoolMethodEntry().getStackConsumeCount() + 1); // + 1 to account for instance 'this'
+
+      }
+
+      @Override int getStackProduceCount() {
+         return (getConstantPoolMethodEntry().getStackProduceCount());
+      }
+   }
+
+   static class I_INVOKESTATIC extends Index16 implements MethodCall{
+      I_INVOKESTATIC(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.INVOKESTATIC, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop args and call the  static method referenced by 16 bit constant index");
+      }
+
+      @Override public int getConstantPoolMethodIndex() {
+         return (index);
+      }
+
+      @Override public ConstantPool.MethodEntry getConstantPoolMethodEntry() {
+         return (method.getConstantPool().getMethodEntry(getConstantPoolMethodIndex()));
+      }
+
+      @Override public Instruction getArg(int _arg) {
+         Instruction child = getFirstChild();
+
+         while (_arg-- != 0) {
+            child = child.getNextExpr();
+         }
+         return (child);
+      }
+
+      @Override int getStackConsumeCount() {
+         return (getConstantPoolMethodEntry().getStackConsumeCount());
+
+      }
+
+      @Override int getStackProduceCount() {
+         return (getConstantPoolMethodEntry().getStackProduceCount());
+      }
+   }
+
+   static class I_INVOKEVIRTUAL extends Index16 implements VirtualMethodCall{
+      I_INVOKEVIRTUAL(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.INVOKEVIRTUAL, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop object reference and args and call the method referenced by 16 bit constant index");
+      }
+
+      @Override public int getConstantPoolMethodIndex() {
+         return (index);
+      }
+
+      @Override public ConstantPool.MethodEntry getConstantPoolMethodEntry() {
+         return (method.getConstantPool().getMethodEntry(getConstantPoolMethodIndex()));
+      }
+
+      @Override public Instruction getArg(int _arg) {
+         Instruction child = getFirstChild();
+         _arg++;
+         while (_arg-- != 0) {
+            child = child.getNextExpr();
+         }
+         return (child);
+      }
+
+      @Override public Instruction getInstanceReference() {
+         return (getFirstChild());
+      }
+
+      @Override int getStackConsumeCount() {
+         return (getConstantPoolMethodEntry().getStackConsumeCount() + 1); // + 1 to account for instance 'this'
+      }
+
+      @Override int getStackProduceCount() {
+         return (getConstantPoolMethodEntry().getStackProduceCount());
+      }
+   }
+
+   static class I_IOR extends BinaryOperator{
+      I_IOR(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IOR, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("or top two ints");
+      }
+
+   }
+
+   static class I_IREM extends BinaryOperator{
+      I_IREM(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IREM, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("rem top two ints");
+      }
+
+   }
+
+   static class I_IRETURN extends Return{
+      I_IRETURN(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IRETURN, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("return popped int");
+      }
+
+   }
+
+   static class I_ISHL extends BinaryOperator{
+      I_ISHL(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ISHL, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("shift left top int");
+      }
+
+   }
+
+   static class I_ISHR extends BinaryOperator{
+      I_ISHR(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ISHR, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("shift right top int");
+      }
+
+   }
+
+   static class I_ISTORE extends LocalVariableIndex08Store{
+      I_ISTORE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ISTORE, _byteReader);
+
+      }
+
+   }
+
+   static class I_ISTORE_0 extends LocalVariableConstIndexStore{
+      I_ISTORE_0(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ISTORE_0, _byteReader, 0);
+
+      }
+
+   }
+
+   static class I_ISTORE_1 extends LocalVariableConstIndexStore{
+      I_ISTORE_1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ISTORE_1, _byteReader, 1);
+
+      }
+
+   }
+
+   static class I_ISTORE_2 extends LocalVariableConstIndexStore{
+      I_ISTORE_2(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ISTORE_2, _byteReader, 2);
+
+      }
+
+   }
+
+   static class I_ISTORE_3 extends LocalVariableConstIndexStore{
+      I_ISTORE_3(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ISTORE_3, _byteReader, 3);
+
+      }
+
+   }
+
+   static class I_ISUB extends BinaryOperator{
+      I_ISUB(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.ISUB, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("sub top two ints");
+      }
+
+   }
+
+   static class I_IUSHR extends BinaryOperator{
+      I_IUSHR(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IUSHR, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("shift right top int unsigned");
+      }
+
+   }
+
+   static class I_IXOR extends BinaryOperator{
+      I_IXOR(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.IXOR, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("xor top two ints");
+      }
+
+   }
+
+   static class I_JSR extends UnconditionalBranch16{
+      I_JSR(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.JSR, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("jump to subroutine ");
+      }
+
+   }
+
+   static class I_JSR_W extends Branch32{
+      I_JSR_W(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.JSR_W, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("subroutine");
+      }
+
+   }
+
+   static class I_L2D extends CastOperator{
+      I_L2D(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.L2D, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop long push double");
+      }
+
+   }
+
+   static class I_L2F extends CastOperator{
+      I_L2F(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.L2F, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop long push float");
+      }
+
+   }
+
+   static class I_L2I extends CastOperator{
+      I_L2I(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.L2I, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop long push int");
+      }
+
+   }
+
+   static class I_LADD extends BinaryOperator{
+      I_LADD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LADD, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("add top two longs");
+      }
+
+   }
+
+   static class I_LALOAD extends AccessArrayElement{
+      I_LALOAD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LALOAD, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push long from arrayref and index");
+      }
+
+   }
+
+   static class I_LAND extends BinaryOperator{
+      I_LAND(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LAND, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("and top two longs");
+      }
+
+   }
+
+   static class I_LASTORE extends AssignToArrayElement{
+      I_LASTORE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LASTORE, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop long into arrayref[index]");
+      }
+
+   }
+
+   static class I_LCMP extends BinaryOperator{
+      I_LCMP(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LCMP, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push result of long comparison");
+      }
+
+   }
+
+   static class I_LCONST_0 extends BytecodeEncodedConstant<Long>{
+      I_LCONST_0(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LCONST_0, _byteReader, 0L);
+
+      }
+
+      @Override String getDescription() {
+         return ("push (long) 0");
+      }
+
+   }
+
+   static class I_LCONST_1 extends BytecodeEncodedConstant<Long>{
+      I_LCONST_1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LCONST_1, _byteReader, 1L);
+
+      }
+
+      @Override String getDescription() {
+         return ("push (long) 1");
+      }
+
+   }
+
+   static class I_LDC extends Index08 implements ConstantPoolEntryConstant{
+      I_LDC(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LDC, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push constant at 08 bit index");
+      }
+
+      @Override public Object getValue() {
+         return (method.getConstantPool().getConstantEntry(getConstantPoolIndex()));
+
+      }
+
+      @Override public int getConstantPoolIndex() {
+         return (index);
+      }
+
+      @Override public Entry getConstantPoolEntry() {
+         return (method.getConstantPool().get(getConstantPoolIndex()));
+      }
+
+   }
+
+   static class I_LDC_W extends Index16 implements ConstantPoolEntryConstant{
+      I_LDC_W(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LDC_W, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push constant at 16 bit index");
+      }
+
+      @Override public int getConstantPoolIndex() {
+         return (index);
+      }
+
+      @Override public Object getValue() {
+         return (method.getConstantPool().getConstantEntry(getConstantPoolIndex()));
+
+      }
+
+      @Override public Entry getConstantPoolEntry() {
+         return (method.getConstantPool().get(getConstantPoolIndex()));
+      }
+
+   }
+
+   static class I_LDC2_W extends Index16 implements ConstantPoolEntryConstant{
+      I_LDC2_W(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LDC2_W, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push long/double constant at 16 bit index");
+      }
+
+      @Override public int getConstantPoolIndex() {
+         return (index);
+      }
+
+      @Override public Entry getConstantPoolEntry() {
+         return (method.getConstantPool().get(getConstantPoolIndex()));
+      }
+
+      @Override public Object getValue() {
+         return (method.getConstantPool().getConstantEntry(getConstantPoolIndex()));
+
+      }
+   }
+
+   static class I_LDIV extends BinaryOperator{
+      I_LDIV(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LDIV, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("div top two longs");
+      }
+
+   }
+
+   static class I_LLOAD extends LocalVariableIndex08Load{
+      I_LLOAD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LLOAD, _byteReader);
+
+      }
+
+   }
+
+   static class I_LLOAD_0 extends LocalVariableConstIndexLoad{
+      I_LLOAD_0(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LLOAD_0, _byteReader, 0);
+
+      }
+
+   }
+
+   static class I_LLOAD_1 extends LocalVariableConstIndexLoad{
+      I_LLOAD_1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LLOAD_1, _byteReader, 1);
+
+      }
+
+   }
+
+   static class I_LLOAD_2 extends LocalVariableConstIndexLoad{
+      I_LLOAD_2(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LLOAD_2, _byteReader, 2);
+
+      }
+
+   }
+
+   static class I_LLOAD_3 extends LocalVariableConstIndexLoad{
+      I_LLOAD_3(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LLOAD_3, _byteReader, 3);
+
+      }
+
+   }
+
+   static class I_LMUL extends BinaryOperator{
+      I_LMUL(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LMUL, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("mul top two longs");
+      }
+
+   }
+
+   static class I_LNEG extends UnaryOperator{
+      I_LNEG(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LNEG, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("neg top long");
+      }
+
+   }
+
+   static class I_LOOKUPSWITCH extends Switch{
+      private int[] matches;
+
+      private int npairs;
+
+      I_LOOKUPSWITCH(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LOOKUPSWITCH, _byteReader);
+         int operandStart = _byteReader.getOffset();
+         int padLength = ((operandStart % 4) == 0) ? 0 : 4 - (operandStart % 4);
+         _byteReader.bytes(padLength);
+         offset = _byteReader.u4();
+         npairs = _byteReader.u4();
+         offsets = new int[npairs];
+         matches = new int[npairs];
+         for (int i = 0; i < npairs; i++) {
+            matches[i] = _byteReader.u4();
+            offsets[i] = _byteReader.u4();
+         }
+
+      }
+
+      @Override String getDescription() {
+         return ("help!");
+      }
+
+      int[] getMatches() {
+         return (matches);
+      }
+
+      int getNpairs() {
+         return (npairs);
+      }
+
+   }
+
+   static class I_LOR extends BinaryOperator{
+      I_LOR(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LOR, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("or top two longs");
+      }
+
+   }
+
+   static class I_LREM extends BinaryOperator{
+      I_LREM(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LREM, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("rem top two longs");
+      }
+
+   }
+
+   static class I_LRETURN extends Return{
+      I_LRETURN(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LRETURN, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("return popped long");
+      }
+
+   }
+
+   static class I_LSHL extends BinaryOperator{
+      I_LSHL(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LSHL, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("shift left top long");
+      }
+
+   }
+
+   static class I_LSHR extends BinaryOperator{
+      I_LSHR(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LSHR, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("shift right top long");
+      }
+
+   }
+
+   static class I_LSTORE extends LocalVariableIndex08Store{
+      I_LSTORE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LSTORE, _byteReader);
+
+      }
+
+   }
+
+   static class I_LSTORE_0 extends LocalVariableConstIndexStore{
+      I_LSTORE_0(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LSTORE_0, _byteReader, 0);
+
+      }
+
+   }
+
+   static class I_LSTORE_1 extends LocalVariableConstIndexStore{
+      I_LSTORE_1(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LSTORE_1, _byteReader, 1);
+
+      }
+
+   }
+
+   static class I_LSTORE_2 extends LocalVariableConstIndexStore{
+      I_LSTORE_2(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LSTORE_2, _byteReader, 2);
+
+      }
+
+   }
+
+   static class I_LSTORE_3 extends LocalVariableConstIndexStore{
+      I_LSTORE_3(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LSTORE_3, _byteReader, 3);
+
+      }
+
+   }
+
+   static class I_LSUB extends BinaryOperator{
+      I_LSUB(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LSUB, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("sub top two longs");
+      }
+
+   }
+
+   static class I_LUSHR extends BinaryOperator{
+      I_LUSHR(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LUSHR, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("shift right top long unsigned");
+      }
+
+   }
+
+   static class I_LXOR extends BinaryOperator{
+      I_LXOR(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.LXOR, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("xor top two longs");
+      }
+
+   }
+
+   static class I_MONITORENTER extends Instruction{
+      I_MONITORENTER(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.MONITORENTER, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop reference and inc monitor");
+      }
+
+   }
+
+   static class I_MONITOREXIT extends Instruction{
+      I_MONITOREXIT(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.MONITOREXIT, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop reference and dec monitor");
+      }
+
+   }
+
+   static class I_MULTIANEWARRAY extends Index16 implements New{
+      private int dimensions;
+
+      I_MULTIANEWARRAY(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.MULTIANEWARRAY, _byteReader);
+         dimensions = _byteReader.u1();
+
+      }
+
+      @Override String getDescription() {
+         return ("create a multi dimension array of refernce types ");
+      }
+
+      int getDimensions() {
+         return (dimensions);
+      }
+
+   }
+
+   static class I_NEW extends Index16 implements New{
+      I_NEW(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.NEW, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("new");
+      }
+
+   }
+
+   static class I_NEWARRAY extends Instruction implements New{
+      private int type;
+
+      I_NEWARRAY(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.NEWARRAY, _byteReader);
+         type = _byteReader.u1();
+
+      }
+
+      @Override String getDescription() {
+         return ("new array simple type");
+      }
+
+      int getType() {
+         return (type);
+      }
+
+   }
+
+   static class I_NOP extends Instruction{
+      I_NOP(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.NOP, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("no op");
+      }
+
+   }
+
+   static class I_POP extends Instruction{
+      I_POP(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.POP, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop one item");
+      }
+
+   }
+
+   static class I_POP2 extends Instruction{
+      I_POP2(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.POP2, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop 2 items");
+      }
+
+   }
+
+   static class I_PUTFIELD extends Index16 implements AssignToInstanceField{
+      I_PUTFIELD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.PUTFIELD, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop stack value into field referenced by 16 bit constant index");
+      }
+
+      @Override public int getConstantPoolFieldIndex() {
+         return (index);
+      }
+
+      @Override public FieldEntry getConstantPoolFieldEntry() {
+         return (method.getConstantPool().getFieldEntry(getConstantPoolFieldIndex()));
+      }
+
+      @Override int getStackConsumeCount() {
+         return (2);
+      }
+
+      @Override int getStackProduceCount() {
+         return (0);
+      }
+
+      @Override public Instruction getInstance() {
+         return (getFirstChild());
+      }
+
+      @Override public Instruction getValueToAssign() {
+         return (getLastChild());
+      }
+
+   }
+
+   static class I_PUTSTATIC extends Index16 implements AssignToField{
+      I_PUTSTATIC(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.PUTSTATIC, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop stack value into 16 bit constant index as field");
+      }
+
+      @Override public int getConstantPoolFieldIndex() {
+         return (index);
+      }
+
+      @Override public FieldEntry getConstantPoolFieldEntry() {
+         return (method.getConstantPool().getFieldEntry(getConstantPoolFieldIndex()));
+      }
+
+      @Override int getStackConsumeCount() {
+         return (1);
+      }
+
+      @Override int getStackProduceCount() {
+         return (0);
+      }
+
+      @Override public Instruction getValueToAssign() {
+         return (getLastChild());
+      }
+   }
+
+   static class I_RET extends Index08 implements AssignToLocalVariable{
+      I_RET(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.RET, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("return to pc in local var index 08 bit");
+      }
+
+      @Override public LocalVariableInfo getLocalVariableInfo() {
+         return (method.getLocalVariableTableEntry().getVariable(getThisPC() + getLength(), getLocalVariableTableIndex()));
+      }
+
+      @Override public boolean isDeclaration() {
+         return (method.getLocalVariableTableEntry().getVariable(getThisPC() + getLength(), getLocalVariableTableIndex())
+               .getStart() == getThisPC() + getLength());
+      }
+
+      @Override public int getLocalVariableTableIndex() {
+         return (index);
+      }
+
+      // @Override  Instruction getValue() {
+      //    return (getFirstChild());
+      //}
+   }
+
+   static class I_RETURN extends Return{
+      I_RETURN(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.RETURN, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("return void");
+      }
+
+   }
+
+   static class I_SALOAD extends AccessArrayElement{
+      I_SALOAD(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.SALOAD, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("push short from arrayref and index");
+      }
+
+   }
+
+   static class I_SASTORE extends AssignToArrayElement{
+      I_SASTORE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.SASTORE, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("pop short into arrayref[index]");
+      }
+
+   }
+
+   static class I_SIPUSH extends ImmediateConstant<Integer>{
+      I_SIPUSH(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.SIPUSH, _byteReader);
+         value = _byteReader.u2();
+
+      }
+
+      @Override String getDescription() {
+         return ("push (short)");
+      }
+   }
+
+   static class I_SWAP extends Instruction{
+      I_SWAP(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.SWAP, _byteReader);
+
+      }
+
+      @Override String getDescription() {
+         return ("swap top 2 items");
+      }
+
+   }
+
+   static class I_TABLESWITCH extends Switch{
+      private int high;
+
+      private int low;
+
+      I_TABLESWITCH(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.TABLESWITCH, _byteReader);
+         int operandStart = _byteReader.getOffset();
+         int padLength = ((operandStart % 4) == 0) ? 0 : 4 - (operandStart % 4);
+         _byteReader.bytes(padLength);
+         offset = _byteReader.u4();
+         low = _byteReader.u4();
+         high = _byteReader.u4();
+         offsets = new int[high - low + 1];
+         for (int i = low; i <= high; i++) {
+            offsets[i - low] = _byteReader.u4();
+         }
+
+      }
+
+      @Override String getDescription() {
+         return ("help!");
+      }
+
+      int getHigh() {
+         return (high);
+      }
+
+      int getLow() {
+         return (low);
+      }
+
+   }
+
+   static class I_WIDE extends Instruction{
+      private boolean iinc;
+
+      private int increment;
+
+      private int index;
+
+      private int wideopcode;
+
+      I_WIDE(MethodModel _methodPoolEntry, ByteReader _byteReader) {
+         super(_methodPoolEntry, ByteCode.WIDE, _byteReader);
+         wideopcode = _byteReader.u1();
+         index = _byteReader.u2();
+         if (((wideopcode >= 0x15 && wideopcode <= 0x19) || (wideopcode >= 0x36 && wideopcode <= 0x3a) || (wideopcode == 0xa9))) {
+            iinc = false;
+         } else {
+            increment = _byteReader.u2();
+            iinc = true;
+         }
+
+      }
+
+      @Override String getDescription() {
+         return ("help");
+      }
+
+      int getIncrement() {
+         return (increment);
+      }
+
+      int getIndex() {
+         return (index);
+      }
+
+      int getWideopcode() {
+         return (wideopcode);
+      }
+
+      boolean isiinc() {
+         return (iinc);
+      }
+
+   }
+
+   static class I_END extends Instruction{
+
+      protected I_END(MethodModel method, int _pc) {
+         super(method, ByteCode.NONE, _pc);
+      }
+
+      @Override String getDescription() {
+         return ("END");
+      }
+   }
+
+   static abstract class Index extends Instruction{
+      protected int index;
+
+      Index(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+
+      }
+
+   }
+
+   static abstract class IndexConst extends Index{
+
+      IndexConst(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader, int _index) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+         index = _index;
+
+      }
+
+   }
+
+   static abstract class Index08 extends Index{
+      Index08(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+         index = _byteReader.u1();
+
+      }
+   }
+
+   static abstract class Index16 extends Index{
+      Index16(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+         index = _byteReader.u2();
+
+      }
+
+   }
+
+   static abstract class Return extends Instruction{
+
+      Return(MethodModel _methodPoolEntry, ByteCode _byteCode, ByteReader _byteReader) {
+         super(_methodPoolEntry, _byteCode, _byteReader);
+
+      }
+
+   }
+
+   static abstract class Switch extends Branch{
+
+      Switch(MethodModel _methodPoolEntry, ByteCode _code, ByteReader _byteReader) {
+         super(_methodPoolEntry, _code, _byteReader);
+      }
+
+      protected int[] offsets;
+
+      protected Instruction[] targets;
+
+      Instruction getTarget(int _index) {
+         return (targets[_index]);
+      }
+
+      void setTarget(int _index, Instruction _instruction) {
+         targets[_index] = _instruction;
+      }
+
+      int getAbsolute(int _index) {
+         return (getThisPC() + offsets[_index]);
+      }
+
+      int getOffset(int _index) {
+         return (offsets[_index]);
+      }
+
+      int[] getOffsets() {
+         return (offsets);
+      }
+
+      int getSize() {
+         return (offsets.length);
+      }
+
+   }
+
+   interface MethodCall{
+      int getConstantPoolMethodIndex();
+
+      MethodEntry getConstantPoolMethodEntry();
+
+      Instruction getArg(int _arg);
+
+   }
+
+   interface VirtualMethodCall extends MethodCall{
+
+      Instruction getInstanceReference();
+   }
+
+   interface InterfaceConstantPoolMethodIndexAccessor{
+      int getConstantPoolInterfaceMethodIndex();
+
+      ConstantPool.InterfaceMethodEntry getConstantPoolInterfaceMethodEntry();
+
+      Instruction getInstanceReference();
+
+      int getArgs();
+
+      Instruction getArg(int _arg);
+   }
+
+   static interface New{
+   }
+
+   interface FieldReference{
+      int getConstantPoolFieldIndex();
+
+      FieldEntry getConstantPoolFieldEntry();
+   }
+
+   interface AccessField extends FieldReference{
+
+   }
+
+   interface AssignToField extends FieldReference{
+      Instruction getValueToAssign();
+   }
+
+   interface AccessInstanceField extends AccessField{
+      Instruction getInstance();
+   }
+
+   interface AssignToInstanceField extends AssignToField{
+      Instruction getInstance();
+   }
+
+   interface LocalVariableTableIndexAccessor{
+      int getLocalVariableTableIndex();
+
+      LocalVariableInfo getLocalVariableInfo();
+   }
+
+   interface AccessLocalVariable extends LocalVariableTableIndexAccessor{
+
+   }
+
+   interface AssignToLocalVariable extends LocalVariableTableIndexAccessor{
+      boolean isDeclaration();
+   }
+
+   interface Constant<T> {
+      T getValue();
+   }
+
+   @SuppressWarnings("unchecked") interface ConstantPoolEntryConstant extends Constant{
+      int getConstantPoolIndex();
+
+      ConstantPool.Entry getConstantPoolEntry();
+   };
+
+   interface HasOperator{
+      Operator getOperator();
+   }
+
+   interface Binary extends HasOperator{
+      Instruction getLhs();
+
+      Instruction getRhs();
+   }
+
+   interface Unary extends HasOperator{
+      Instruction getUnary();
+   }
+
+   static class CloneInstruction extends Instruction{
+      private Instruction cloning;
+
+      CloneInstruction(MethodModel method, Instruction _cloning) {
+         super(method, ByteCode.CLONE, -1);
+         cloning = _cloning;
+      }
+
+      @Override String getDescription() {
+         return ("CLONE! " + getByteCode());
+      }
+
+      @Override int getStackConsumeCount() {
+         return (cloning.getStackConsumeCount());
+      }
+
+      @Override int getStackProduceCount() {
+         return (cloning.getStackProduceCount());
+      }
+
+      @Override Instruction getReal() {
+         return (cloning);
+      }
+   }
+
+   static class IncrementInstruction extends Instruction{
+      private Instruction fieldOrVariable;
+
+      private boolean isInc;
+
+      private boolean isPre;
+
+      Instruction getFieldOrVariableReference() {
+         return fieldOrVariable;
+      }
+
+      boolean isPre() {
+         return isPre;
+      }
+
+      IncrementInstruction(MethodModel method, Instruction _fieldOrVariable, boolean _isInc, boolean _isPre) {
+         super(method, ByteCode.INCREMENT, -1);
+
+         fieldOrVariable = _fieldOrVariable;
+         isPre = _isPre;
+         isInc = _isInc;
+      }
+
+      @Override String getDescription() {
+         return ("INCREMENT Local Variable! " + getByteCode());
+      }
+
+      boolean isInc() {
+         return (isInc);
+      }
+
+      @Override Instruction getStartInstruction() {
+         return (fieldOrVariable.getStartInstruction());
+      }
+   }
+
+   static class InlineAssignInstruction extends Instruction{
+      AssignToLocalVariable assignToLocalVariable;
+
+      Instruction rhs;
+
+      InlineAssignInstruction(MethodModel method, AssignToLocalVariable _assignToLocalVariable, Instruction _rhs) {
+         super(method, ByteCode.INLINE_ASSIGN, -1);
+         assignToLocalVariable = _assignToLocalVariable;
+         rhs = _rhs;
+
+      }
+
+      @Override String getDescription() {
+         return ("INLINE ASSIGN! " + getByteCode());
+      }
+
+      AssignToLocalVariable getAssignToLocalVariable() {
+         return (assignToLocalVariable);
+      }
+
+      Instruction getRhs() {
+         return (rhs);
+      }
+   }
+
+   static class FieldArrayElementAssign extends Instruction{
+      AssignToArrayElement assignToArrayElement;
+
+      Instruction rhs;
+
+      FieldArrayElementAssign(MethodModel method, AssignToArrayElement _assignToArrayElement, Instruction _rhs) {
+         super(method, ByteCode.FIELD_ARRAY_ELEMENT_ASSIGN, -1);
+         assignToArrayElement = _assignToArrayElement;
+         rhs = _rhs;
+
+      }
+
+      @Override String getDescription() {
+         return ("FIELD ARRAY ELEMENT INCREMENT! " + getByteCode());
+      }
+
+      AssignToArrayElement getAssignToArrayElement() {
+         return (assignToArrayElement);
+      }
+
+      Instruction getRhs() {
+         return (rhs);
+      }
+
+   }
+
+   static class FieldArrayElementIncrement extends Instruction{
+      AssignToArrayElement assignToArrayElement;
+
+      boolean isPre;
+
+      boolean isInc;
+
+      FieldArrayElementIncrement(MethodModel method, AssignToArrayElement _assignToArrayElement, boolean _isInc, boolean _isPre) {
+         super(method, ByteCode.FIELD_ARRAY_ELEMENT_INCREMENT, -1);
+         assignToArrayElement = _assignToArrayElement;
+         isPre = _isPre;
+         isInc = _isInc;
+
+      }
+
+      @Override String getDescription() {
+         return ("FIELD ARRAY ELEMENT INCREMENT! " + getByteCode());
+      }
+
+      AssignToArrayElement getAssignToArrayElement() {
+         return (assignToArrayElement);
+      }
+
+      boolean isPre() {
+         return (isPre);
+      }
+
+      boolean isInc() {
+         return (isInc);
+      }
+   }
+
+   static class MultiAssignInstruction extends Instruction{
+      Instruction from, to, common;
+
+      MultiAssignInstruction(MethodModel method, Instruction _common, Instruction _from, Instruction _to) {
+         super(method, ByteCode.MULTI_ASSIGN, -1);
+         common = _common;
+         from = _from;
+         to = _to;
+      }
+
+      @Override String getDescription() {
+         return ("MULTIASSIGN! " + getByteCode());
+      }
+
+      Instruction getTo() {
+         return (to);
+      }
+
+      Instruction getFrom() {
+         return (from);
+      }
+
+      Instruction getCommon() {
+         return (common);
+      }
+   }
+
+   static class FakeGoto extends UnconditionalBranch{
+
+      FakeGoto(MethodModel _methodPoolEntry, Instruction _target) {
+         super(_methodPoolEntry, ByteCode.FAKEGOTO, _target);
+      }
+
+      @Override String getDescription() {
+
+         return "FAKE goto";
+      }
+
+   }
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/InstructionTransformer.java b/com.amd.aparapi/src/java/com/amd/aparapi/InstructionTransformer.java
new file mode 100644
index 00000000..db54f865
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/InstructionTransformer.java
@@ -0,0 +1,52 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+public abstract class InstructionTransformer{
+   private String description;
+
+   public abstract Instruction transform(final ExpressionList _expressionList, final Instruction i);
+
+   InstructionTransformer(String _description) {
+      description = _description;
+   }
+
+   public String getDescription() {
+      return (description);
+   }
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/Kernel.java b/com.amd.aparapi/src/java/com/amd/aparapi/Kernel.java
new file mode 100644
index 00000000..33b5cc4e
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/Kernel.java
@@ -0,0 +1,1873 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+import java.util.logging.Logger;
+
+import com.amd.aparapi.ClassModel.ConstantPool.MethodReferenceEntry;
+
+/**
+ * A <i>kernel</i> encapsulates a data parallel algorithm that will execute either on a GPU
+ * (through conversion to OpenCL) or on a CPU via a Java Thread Pool. 
+ * <p>
+ * To write a new kernel, a developer extends the <code>Kernel</code> class and overrides the <code>Kernel.run()</code> method.
+ * To execute this kernel, the developer creates a new instance of it and calls <code>Kernel.execute(int globalSize)</code> with a suitable 'global size'. At runtime
+ * Aparapi will attempt to convert the <code>Kernel.run()</code> method (and any method called directly or indirectly
+ * by <code>Kernel.run()</code>) into OpenCL for execution on GPU devices made available via the OpenCL platform. 
+ * <p>
+ * Note that <code>Kernel.run()</code> is not called directly. Instead, 
+ * the <code>Kernel.execute(int globalSize)</code> method will cause the overridden <code>Kernel.run()</code> 
+ * method to be invoked once for each value in the range <code>0...globalSize</code>.
+ * <p>
+ * On the first call to <code>Kernel.execute(int _globalSize)</code>, Aparapi will determine the EXECUTION_MODE of the kernel. 
+ * This decision is made dynamically based on two factors:
+ * <ol>
+ * <li>Whether OpenCL is available (appropriate drivers are installed and the OpenCL and Aparapi dynamic libraries are included on the system path).</li>
+ * <li>Whether the bytecode of the <code>run()</code> method (and every method that can be called directly or indirectly from the <code>run()</code> method)
+ *  can be converted into OpenCL.</li>
+ * </ol>
+ * <p>
+ * Below is an example Kernel that calculates the square of a set of input values.
+ * <p>
+ * <blockquote><pre>
+ *     class SquareKernel extends Kernel{
+ *         private int values[];
+ *         private int squares[];
+ *         public SquareKernel(int values[]){
+ *            this.values = values;
+ *            squares = new int[values.length];
+ *         }
+ *         public void run() {
+ *             int gid = getGlobalID();
+ *             squares[gid] = values[gid]*values[gid];
+ *         }
+ *         public int[] getSquares(){
+ *             return(squares);
+ *         }
+ *     }
+ * </pre></blockquote>
+ * <p>
+ * To execute this kernel, first create a new instance of it and then call <code>execute(int globalSize)</code>. 
+ * <p>
+ * <blockquote><pre>
+ *     int[] values = new int[1024];
+ *     // fill values array
+ *     SquareKernel kernel = new SquareKernel(values);
+ *     kernel.execute(values.length);
+ * </pre></blockquote>
+ * <p>
+ * When <code>execute()</code> returns, all the executions of Kernel.run() have completed and the results are available in the <code>squares</code> array.
+ * <p>
+ * <blockquote><pre>
+ *     int[] squares = kernel.getSquares();
+ *     for (int i=0; i< values.length; i++){
+ *        System.out.printf("%4d %4d %8d\n", i, values[i], squares[i]);
+ *     }
+ * </pre></blockquote>
+ * <p>
+ * A different approach to creating kernels that avoids extending Kernel is to write an anonymous inner class:
+ * <p>
+ * <blockquote><pre>
+ *     final int[] values = new int[1024];
+ *     // fill values array
+ *     final int[] squares = new int[values.length];
+ *     Kernel kernel = new Kernel(){
+ *         public void run() {
+ *             int gid = getGlobalID();
+ *             squares[gid] = values[gid]*values[gid];
+ *         }
+ *     };
+ *     kernel.execute(values.length);
+ *     for (int i=0; i< values.length; i++){
+ *        System.out.printf("%4d %4d %8d\n", i, values[i], squares[i]);
+ *     }
+ *     
+ * </pre></blockquote>
+ * <p>
+ *
+ * @author  gfrost AMD Javalabs
+ * @version Alpha, 21/09/2010
+ */
+
+public abstract class Kernel implements Cloneable{
+   @Retention(RetentionPolicy.RUNTIME) @interface OpenCLMapping {
+      String mapTo() default "";
+
+      boolean atomic32() default false;
+
+      boolean atomic64() default false;
+   }
+
+   @Retention(RetentionPolicy.RUNTIME) @interface OpenCLDelegate {
+   }
+
+   private static Logger logger = Logger.getLogger(Config.getLoggerName());
+
+   public abstract class Entry{
+      public abstract void run();
+
+      public Kernel execute(int _globalSize) {
+         return (Kernel.this.execute("foo", _globalSize, 1));
+      }
+   }
+
+   /**
+    * The <i>execution mode</i> ENUM enumerates the possible modes of executing a kernel. 
+    * One can request a mode of execution using the values below, and query a kernel after it first executes to 
+    * determine how it executed.  
+    *    
+    * <p>
+    * Aparapi supports 4 execution modes. 
+    * <ul>
+    * <table>
+    * <tr><th align="left">Enum value</th><th align="left">Execution</th></tr>
+    * <tr><td><code><b>GPU</b></code></td><td>Execute using OpenCL on first available GPU device</td></tr>
+    * <tr><td><code><b>CPU</b></code></td><td>Execute using OpenCL on first available CPU device</td></tr>
+    * <tr><td><code><b>JTP</b></code></td><td>Execute using a Java Thread Pool (one thread spawned per available core)</td></tr>
+    * <tr><td><code><b>SEQ</b></code></td><td>Execute using a single loop. This is useful for debugging but will be less 
+    * performant than the other modes</td></tr>
+    * </table>
+    * </ul>
+    * <p>
+    * To request that a kernel is executed in a specific mode, call <code>Kernel.setExecutionMode(EXECUTION_MODE)</code> before the
+    *  kernel first executes.
+    * <p>
+    * <blockquote><pre>
+    *     int[] values = new int[1024];
+    *     // fill values array
+    *     SquareKernel kernel = new SquareKernel(values);
+    *     kernel.setExecutionMode(Kernel.EXECUTION_MODE.JTP);
+    *     kernel.execute(values.length);
+    * </pre></blockquote>
+    * <p>
+    * Alternatively, the property <code>com.amd.aparapi.executionMode</code> can be set to one of <code>JTP,GPU,CPU,SEQ</code>
+    * when an application is launched. 
+    * <p><blockquote><pre>
+    *    java -classpath ....;aparapi.jar -Dcom.amd.aparapi.executionMode=GPU MyApplication  
+    * </pre></blockquote><p>
+    * Generally setting the execution mode is not recommended (it is best to let Aparapi decide automatically) but the option
+    * provides a way to compare a kernel's performance under multiple execution modes.
+    * 
+    * @author  gfrost AMD Javalabs
+    * @version Alpha, 21/09/2010
+    */
+
+   public static enum EXECUTION_MODE {
+      /**
+       * A dummy value to indicate an unknown state.
+       */
+      NONE,
+      /**
+       * The value representing execution on a GPU device via OpenCL.
+       */
+      GPU,
+      /**
+       * The value representing execution on a CPU device via OpenCL.
+       * <p>
+       * <b>Note</b> not all OpenCL implementations support OpenCL compute on the CPU. 
+       */
+      CPU,
+      /**
+       * The value representing execution on a Java Thread Pool.
+       * <p>
+       * By default one Java thread is started for each available core and each core will execute <code>globalSize/cores</code> work items.
+       * This creates a total of <code>globalSize%cores</code> threads to complete the work.  
+       * Choose suitable values for <code>globalSize</code> to minimize the number of threads that are spawned. 
+       */
+      JTP,
+      /**
+       * The value representing execution sequentially in a single loop.
+       * <p>
+       * This is meant to be used for debugging a kernel.
+       */
+      SEQ;
+      static boolean openCLAvailable;
+
+      static {
+         String arch = System.getProperty("os.arch");
+         logger.fine("arch = " + arch);
+
+         String libName = null;
+         try {
+
+            if (arch.equals("amd64")) {
+
+               libName = "aparapi_x86_64";
+               logger.fine("attempting to load shared lib " + libName);
+               System.loadLibrary(libName);
+               openCLAvailable = true;
+            } else if (arch.equals("x86") || arch.equals("i386")) {
+               libName = "aparapi_x86";
+               logger.fine("attempting to load shared lib " + libName);
+               System.loadLibrary(libName);
+               openCLAvailable = true;
+            } else {
+               logger.warning("Expected property os.arch to contain amd64 or x86 but found " + arch
+                     + " don't know which library to load.");
+
+            }
+         } catch (UnsatisfiedLinkError e) {
+            logger
+                  .warning("Check your environment. Failed to load aparapi native library "
+                        + libName
+                        + " or possibly failed to locate opencl native library (opencl.dll/opencl.so). Ensure that both are in your PATH (windows) or in LD_LIBRARY_PATH (linux).");
+
+            openCLAvailable = false;
+         }
+      }
+
+      static EXECUTION_MODE getDefaultExecutionMode() {
+         EXECUTION_MODE defaultExecutionMode = openCLAvailable ? GPU : JTP;
+         String executionMode = Config.executionMode;
+         if (executionMode != null) {
+            try {
+               EXECUTION_MODE requestedExecutionMode = valueOf(executionMode.toUpperCase());
+               logger.fine("requested execution mode = " + requestedExecutionMode);
+               if ((openCLAvailable && requestedExecutionMode.isOpenCL()) || !requestedExecutionMode.isOpenCL()) {
+                  defaultExecutionMode = requestedExecutionMode;
+               }
+            } catch (Throwable t) {
+               // we will take the default
+            }
+         }
+
+         logger.fine("default execution mode = " + defaultExecutionMode);
+
+         return (defaultExecutionMode);
+      }
+
+      static EXECUTION_MODE getFallbackExecutionMode() {
+         EXECUTION_MODE defaultFallbackExecutionMode = JTP;
+         logger.info("fallback execution mode = " + defaultFallbackExecutionMode);
+         return (defaultFallbackExecutionMode);
+      }
+
+      boolean isOpenCL() {
+         return this == GPU || this == CPU;
+      }
+
+   };
+
+   private EXECUTION_MODE executionMode = EXECUTION_MODE.getDefaultExecutionMode();
+
+   private int globalId;
+
+   private int localId;
+
+   private int localSize;
+
+   private int globalSize;
+
+   private int groupId;
+
+   private int passId;
+
+   private int numGroups;
+
+   volatile CyclicBarrier localBarrier;
+
+   void setGlobalId(int _globalId) {
+      globalId = _globalId;
+   }
+
+   /**
+    * Determine the globalId of an executing kernel.
+    * <p>
+    * The kernel implementation uses the globalId to determine which of the executing kernels (in the global domain space) this invocation is expected to deal with. 
+    * <p>
+    * For example in a <code>SquareKernel</code> implementation:
+    * <p>
+    * <blockquote><pre>
+    *     class SquareKernel extends Kernel{
+    *         private int values[];
+    *         private int squares[];
+    *         public SquareKernel(int values[]){
+    *            this.values = values;
+    *            squares = new int[values.length];
+    *         }
+    *         public void run() {
+    *             int gid = getGlobalID();
+    *             squares[gid] = values[gid]*values[gid];
+    *         }
+    *         public int[] getSquares(){
+    *             return(squares);
+    *         }
+    *     }
+    * </pre></blockquote>
+    * <p>
+    * Each invocation of <code>SquareKernel.run()</code> retrieves it's globalId by calling <code>getGlobalId()</code>, and then computes the value of <code>square[gid]</code> for a given value of <code>value[gid]</code>.
+    * <p> 
+    * @return The globalId for the Kernel being executed
+    * 
+    * @see #getLocalId()
+    * @see #getGroupId()
+    * @see #getGlobalSize()
+    * @see #getNumGroups()
+    * @see #getLocalSize()
+    */
+
+   @OpenCLDelegate protected final int getGlobalId() {
+      return (globalId);
+   }
+
+   void setGroupId(int _groupId) {
+      groupId = _groupId;
+
+   }
+
+   void setPassId(int _passId) {
+      passId = _passId;
+
+   }
+
+   /**
+    * Determine the groupId of an executing kernel.
+    * <p>
+    * When a <code>Kernel.execute(int globalSize)</code> is invoked for a particular kernel, the runtime will break the work into various 'groups'.
+    * <p>
+    * A kernel can use <code>getGroupId()</code> to determine which group a kernel is currently 
+    * dispatched to
+    * <p>
+    * The following code would capture the groupId for each kernel and map it against globalId.
+    * <blockquote><pre>
+    *     final int[] groupIds = new int[1024];
+    *     Kernel kernel = new Kernel(){
+    *         public void run() {
+    *             int gid = getGlobalId();
+    *             groupIds[gid] = getGroupId();
+    *         }
+    *     };
+    *     kernel.execute(groupIds.length);
+    *     for (int i=0; i< values.length; i++){
+    *        System.out.printf("%4d %4d\n", i, groupIds[i]);
+    *     } 
+    * </pre></blockquote>
+    * 
+    * @see #getLocalId()
+    * @see #getGlobalId()
+    * @see #getGlobalSize()
+    * @see #getNumGroups()
+    * @see #getLocalSize()
+    * 
+    * @return The groupId for this Kernel being executed
+    */
+   @OpenCLDelegate protected final int getGroupId() {
+      return (groupId);
+   }
+
+   /**
+    * Determine the passId of an executing kernel.
+    * <p>
+    * When a <code>Kernel.execute(int globalSize, int passes)</code> is invoked for a particular kernel, the runtime will break the work into various 'groups'.
+    * <p>
+    * A kernel can use <code>getPassId()</code> to determine which pass we are in.  This is ideal for 'reduce' type phases
+    * 
+    * @see #getLocalId()
+    * @see #getGlobalId()
+    * @see #getGlobalSize()
+    * @see #getNumGroups()
+    * @see #getLocalSize()
+    * 
+    * @return The groupId for this Kernel being executed
+    */
+   @OpenCLDelegate protected final int getPassId() {
+      return (passId);
+   }
+
+   void setLocalId(int _localId) {
+      localId = _localId;
+   }
+
+   /**
+    * Determine the local id of an executing kernel.
+    * <p>
+    * When a <code>Kernel.execute(int globalSize)</code> is invoked for a particular kernel, the runtime will break the work into
+    * various 'groups'.
+    * <code>getLocalId()</code> can be used to determine the relative id of the current kernel within a specific group.
+    * <p>
+    * The following code would capture the groupId for each kernel and map it against globalId.
+    * <blockquote><pre>
+    *     final int[] localIds = new int[1024];
+    *     Kernel kernel = new Kernel(){
+    *         public void run() {
+    *             int gid = getGlobalId();
+    *             localIds[gid] = getLocalId();
+    *         }
+    *     };
+    *     kernel.execute(localIds.length);
+    *     for (int i=0; i< values.length; i++){
+    *        System.out.printf("%4d %4d\n", i, localIds[i]);
+    *     } 
+    * </pre></blockquote>
+    * 
+    * @see #getGroupId()
+    * @see #getGlobalId()
+    * @see #getGlobalSize()
+    * @see #getNumGroups()
+    * @see #getLocalSize()
+    * 
+    * @return The local id for this Kernel being executed
+    */
+   @OpenCLDelegate protected final int getLocalId() {
+      return (localId);
+   }
+
+   /**
+    * Determine the size of the group that an executing kernel is a member of.
+    * <p>
+    * When a <code>Kernel.execute(int globalSize)</code> is invoked for a particular kernel, the runtime will break the work into
+    * various 'groups'. <code>getLocalSize()</code> allows a kernel to determine the size of the current group.
+    * <p>
+    * Note groups may not all be the same size. In particular, if <code>(global size)%(# of compute devices)!=0</code>, the runtime can choose to dispatch kernels to 
+    * groups with differing sizes. 
+    * 
+    * @see #getGroupId()
+    * @see #getGlobalId()
+    * @see #getGlobalSize()
+    * @see #getNumGroups()
+    * @see #getLocalSize()
+    * 
+    * @return The size of the currently executing group.
+    */
+   @OpenCLDelegate protected final int getLocalSize() {
+      return (localSize);
+   }
+
+   /**
+    * Determine the value that was passed to <code>Kernel.execute(int globalSize)</code> method.
+    * 
+    * @see #getGroupId()
+    * @see #getGlobalId()
+    * @see #getNumGroups()
+    * @see #getLocalSize()
+    * 
+    * @return The value passed to <code>Kernel.execute(int globalSize)</code> causing the current execution.
+    */
+   @OpenCLDelegate protected final int getGlobalSize() {
+      return (globalSize);
+   }
+
+   void setNumGroups(int _numGroups) {
+      numGroups = _numGroups;
+
+   }
+
+   /**
+    * Determine the number of groups that will be used to execute a kernel
+    * <p>
+    * When <code>Kernel.execute(int globalSize)</code> is invoked, the runtime will split the work into
+    * multiple 'groups'. <code>getNumGroups()</code> returns the total number of groups that will be used.
+    * 
+    * @see #getGroupId()
+    * @see #getGlobalId()
+    * @see #getGlobalSize()
+    * @see #getNumGroups()
+    * @see #getLocalSize()
+    * 
+    * @return The number of groups that kernels will be dispatched into.
+    */
+   @OpenCLDelegate protected final int getNumGroups() {
+      return (numGroups);
+   }
+
+   /**
+    * The entry point of a kernel. 
+    *  
+    * <p>
+    * Every kernel must override this method.
+    */
+   public abstract void run();
+
+   /**
+    * When using a Java Thread Pool Aparapi uses clone to copy the initial instance to each thread. 
+    *  
+    * <p>
+    * If you choose to override <code>clone()</code> you are responsible for delegating to <code>super.clone();</code>
+    */
+   @Override protected Object clone() {
+      try {
+         Kernel worker = (Kernel) super.clone();
+         // if there are any private buffers, go thru the fields here
+         // and allocate a new instance for each clone
+
+         return worker;
+      } catch (CloneNotSupportedException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+         return (null);
+      }
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#acos(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/acos.html">acos(float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param a value to delegate to {@link java.lang.Math#acos(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/acos.html">acos(float)</a></code>
+     * @return {@link java.lang.Math#acos(double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/acos.html">acos(float)</a></code>
+     * 
+     * @see java.lang.Math#acos(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/acos.html">acos(float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "acos") protected float acos(float a) {
+      return (float) Math.acos(a);
+   }
+
+   /**
+   * Delegates to either {@link java.lang.Math#acos(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/acos.html">acos(double)</a></code> (OpenCL).
+    * 
+    * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+    * 
+    * @param a value to delegate to {@link java.lang.Math#acos(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/acos.html">acos(double)</a></code>
+    * @return {@link java.lang.Math#acos(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/acos.html">acos(double)</a></code>
+    * 
+    * @see java.lang.Math#acos(double)
+    * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/acos.html">acos(double)</a></code>
+    */
+   @OpenCLMapping(mapTo = "acos") protected double acos(double a) {
+      return Math.acos(a);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#asin(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/asin.html">asin(float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f value to delegate to {@link java.lang.Math#asin(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/asin.html">asin(float)</a></code>
+     * @return {@link java.lang.Math#asin(double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/asin.html">asin(float)</a></code>
+     * 
+     * @see java.lang.Math#asin(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/asin.html">asin(float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "asin") protected float asin(float _f) {
+      return (float) Math.asin(_f);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#asin(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/asin.html">asin(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d value to delegate to {@link java.lang.Math#asin(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/asin.html">asin(double)</a></code>
+     * @return {@link java.lang.Math#asin(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/asin.html">asin(double)</a></code>
+     * 
+     * @see java.lang.Math#asin(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/asin.html">asin(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "asin") protected double asin(double _d) {
+      return Math.asin(_d);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#atan(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan(float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f value to delegate to {@link java.lang.Math#atan(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan(float)</a></code>
+     * @return {@link java.lang.Math#atan(double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan(float)</a></code>
+     * 
+     * @see java.lang.Math#atan(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan(float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "atan") protected float atan(float _f) {
+      return (float) Math.atan(_f);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#atan(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d value to delegate to {@link java.lang.Math#atan(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan(double)</a></code>
+     * @return {@link java.lang.Math#atan(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan(double)</a></code>
+     * 
+     * @see java.lang.Math#atan(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "atan") protected double atan(double _d) {
+      return Math.atan(_d);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#atan2(double, double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan2(float, float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f1 value to delegate to first argument of {@link java.lang.Math#atan2(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan2(float, float)</a></code>
+     * @param _f2 value to delegate to second argument of {@link java.lang.Math#atan2(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan2(float, float)</a></code>
+     * @return {@link java.lang.Math#atan2(double, double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan2(float, float)</a></code>
+     * 
+     * @see java.lang.Math#atan2(double, double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan2(float, float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "atan2") protected float atan2(float _f1, float _f2) {
+      return (float) Math.atan2(_f1, _f2);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#atan2(double, double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan2(double, double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d1 value to delegate to first argument of {@link java.lang.Math#atan2(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan2(double, double)</a></code>
+     * @param _d2 value to delegate to second argument of {@link java.lang.Math#atan2(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan2(double, double)</a></code>
+     * @return {@link java.lang.Math#atan2(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan2(double, double)</a></code>
+     * 
+     * @see java.lang.Math#atan2(double, double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atan.html">atan2(double, double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "atan2") protected double atan2(double _d1, double _d2) {
+      return Math.atan2(_d1, _d2);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#ceil(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/ceil.html">ceil(float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f value to delegate to {@link java.lang.Math#ceil(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/ceil.html">ceil(float)</a></code>
+     * @return {@link java.lang.Math#ceil(double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/ceil.html">ceil(float)</a></code>
+     * 
+     * @see java.lang.Math#ceil(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/ceil.html">ceil(float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "ceil") protected float ceil(float _f) {
+      return (float) Math.ceil(_f);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#ceil(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/ceil.html">ceil(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d value to delegate to {@link java.lang.Math#ceil(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/ceil.html">ceil(double)</a></code>
+     * @return {@link java.lang.Math#ceil(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/ceil.html">ceil(double)</a></code>
+     * 
+     * @see java.lang.Math#ceil(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/ceil.html">ceil(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "ceil") protected double ceil(double _d) {
+      return Math.ceil(_d);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#cos(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/cos.html">cos(float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f value to delegate to {@link java.lang.Math#cos(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/cos.html">cos(float)</a></code>
+     * @return {@link java.lang.Math#cos(double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/cos.html">cos(float)</a></code>
+     * 
+     * @see java.lang.Math#cos(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/cos.html">cos(float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "cos") protected float cos(float _f) {
+      return (float) Math.cos(_f);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#cos(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/cos.html">cos(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d value to delegate to {@link java.lang.Math#cos(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/cos.html">cos(double)</a></code>
+     * @return {@link java.lang.Math#cos(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/cos.html">cos(double)</a></code>
+     * 
+     * @see java.lang.Math#cos(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/cos.html">cos(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "cos") protected double cos(double _d) {
+      return Math.cos(_d);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#exp(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/exp.html">exp(float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f value to delegate to {@link java.lang.Math#exp(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/exp.html">exp(float)</a></code>
+     * @return {@link java.lang.Math#exp(double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/exp.html">exp(float)</a></code>
+     * 
+     * @see java.lang.Math#exp(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/exp.html">exp(float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "exp") protected float exp(float _f) {
+      return (float) Math.exp(_f);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#exp(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/exp.html">exp(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d value to delegate to {@link java.lang.Math#exp(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/exp.html">exp(double)</a></code>
+     * @return {@link java.lang.Math#exp(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/exp.html">exp(double)</a></code>
+     * 
+     * @see java.lang.Math#exp(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/exp.html">exp(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "exp") protected double exp(double _d) {
+      return Math.exp(_d);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#abs(float)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fabs.html">fabs(float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f value to delegate to {@link java.lang.Math#abs(float)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fabs.html">fabs(float)</a></code>
+     * @return {@link java.lang.Math#abs(float)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fabs.html">fabs(float)</a></code>
+     * 
+     * @see java.lang.Math#abs(float)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fabs.html">fabs(float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "fabs") protected float abs(float _f) {
+      return Math.abs(_f);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#abs(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fabs.html">fabs(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d value to delegate to {@link java.lang.Math#abs(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fabs.html">fabs(double)</a></code>
+     * @return {@link java.lang.Math#abs(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fabs.html">fabs(double)</a></code>
+     * 
+     * @see java.lang.Math#abs(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fabs.html">fabs(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "fabs") protected double abs(double _d) {
+      return Math.abs(_d);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#abs(int)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/abs.html">abs(int)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param n value to delegate to {@link java.lang.Math#abs(int)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/abs.html">abs(int)</a></code>
+     * @return {@link java.lang.Math#abs(int)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/abs.html">abs(int)</a></code>
+     * 
+     * @see java.lang.Math#abs(int)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/abs.html">abs(int)</a></code>
+     */
+   @OpenCLMapping(mapTo = "abs") protected int abs(int n) {
+      return Math.abs(n);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#abs(long)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/abs.html">abs(long)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param n value to delegate to {@link java.lang.Math#abs(long)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/abs.html">abs(long)</a></code>
+     * @return {@link java.lang.Math#abs(long)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fabs.html">abs(long)</a></code>
+     * 
+     * @see java.lang.Math#abs(long)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/abs.html">abs(long)</a></code>
+     */
+   @OpenCLMapping(mapTo = "abs") protected long abs(long n) {
+      return Math.abs(n);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#floor(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/abs.html">floor(float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f value to delegate to {@link java.lang.Math#floor(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/floor.html">floor(float)</a></code>
+     * @return {@link java.lang.Math#floor(double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/floor.html">floor(float)</a></code>
+     * 
+     * @see java.lang.Math#floor(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/floor.html">floor(float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "floor") protected float floor(float _f) {
+      return (float) Math.floor(_f);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#floor(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/abs.html">floor(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d value to delegate to {@link java.lang.Math#floor(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/floor.html">floor(double)</a></code>
+     * @return {@link java.lang.Math#floor(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/floor.html">floor(double)</a></code>
+     * 
+     * @see java.lang.Math#floor(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/floor.html">floor(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "floor") protected double floor(double _d) {
+      return Math.floor(_d);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#max(float, float)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmax.html">fmax(float, float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f1 value to delegate to first argument of {@link java.lang.Math#max(float, float)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmax.html">fmax(float, float)</a></code>
+     * @param _f2 value to delegate to second argument of {@link java.lang.Math#max(float, float)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmax.html">fmax(float, float)</a></code>
+     * @return {@link java.lang.Math#max(float, float)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmax.html">fmax(float, float)</a></code>
+     * 
+     * @see java.lang.Math#max(float, float)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmax.html">fmax(float, float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "fmax") protected float max(float _f1, float _f2) {
+      return Math.max(_f1, _f2);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#max(double, double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmax.html">fmax(double, double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d1 value to delegate to first argument of {@link java.lang.Math#max(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmax.html">fmax(double, double)</a></code>
+     * @param _d2 value to delegate to second argument of {@link java.lang.Math#max(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmax.html">fmax(double, double)</a></code>
+     * @return {@link java.lang.Math#max(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmax.html">fmax(double, double)</a></code>
+     * 
+     * @see java.lang.Math#max(double, double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmax.html">fmax(double, double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "fmax") protected double max(double _d1, double _d2) {
+      return Math.max(_d1, _d2);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#max(int, int)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">max(int, int)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param n1 value to delegate to {@link java.lang.Math#max(int, int)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">max(int, int)</a></code>
+     * @param n2 value to delegate to {@link java.lang.Math#max(int, int)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">max(int, int)</a></code>
+     * @return {@link java.lang.Math#max(int, int)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">max(int, int)</a></code>
+     * 
+     * @see java.lang.Math#max(int, int)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">max(int, int)</a></code>
+     */
+   @OpenCLMapping(mapTo = "max") protected int max(int n1, int n2) {
+      return Math.max(n1, n2);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#max(long, long)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">max(long, long)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param n1 value to delegate to first argument of {@link java.lang.Math#max(long, long)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">max(long, long)</a></code>
+     * @param n2 value to delegate to second argument of {@link java.lang.Math#max(long, long)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">max(long, long)</a></code>
+     * @return {@link java.lang.Math#max(long, long)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">max(long, long)</a></code>
+     * 
+     * @see java.lang.Math#max(long, long)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">max(long, long)</a></code>
+     */
+   @OpenCLMapping(mapTo = "max") protected long max(long n1, long n2) {
+      return Math.max(n1, n2);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#min(float, float)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmin.html">fmin(float, float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f1 value to delegate to first argument of {@link java.lang.Math#min(float, float)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmin.html">fmin(float, float)</a></code>
+     * @param _f2 value to delegate to second argument of {@link java.lang.Math#min(float, float)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmin.html">fmin(float, float)</a></code>
+     * @return {@link java.lang.Math#min(float, float)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmin.html">fmin(float, float)</a></code>
+     * 
+     * @see java.lang.Math#min(float, float)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmin.html">fmin(float, float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "fmin") protected float min(float _f1, float _f2) {
+      return Math.min(_f1, _f2);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#min(double, double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmin.html">fmin(double, double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d1 value to delegate to first argument of {@link java.lang.Math#min(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmin.html">fmin(double, double)</a></code>
+     * @param _d2 value to delegate to second argument of {@link java.lang.Math#min(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmin.html">fmin(double, double)</a></code>
+     * @return {@link java.lang.Math#min(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmin.html">fmin(double, double)</a></code>
+     * 
+     * @see java.lang.Math#min(double, double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/fmin.html">fmin(double, double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "fmin") protected double min(double _d1, double _d2) {
+      return Math.min(_d1, _d2);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#min(int, int)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">min(int, int)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param n1 value to delegate to first argument of {@link java.lang.Math#min(int, int)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">min(int, int)</a></code>
+     * @param n2 value to delegate to second argument of {@link java.lang.Math#min(int, int)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">min(int, int)</a></code>
+     * @return {@link java.lang.Math#min(int, int)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">min(int, int)</a></code>
+     * 
+     * @see java.lang.Math#min(int, int)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">min(int, int)</a></code>
+     */
+   @OpenCLMapping(mapTo = "min") protected int min(int n1, int n2) {
+      return Math.min(n1, n2);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#min(long, long)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">min(long, long)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param n1 value to delegate to first argument of {@link java.lang.Math#min(long, long)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">min(long, long)</a></code>
+     * @param n2 value to delegate to second argument of {@link java.lang.Math#min(long, long)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">min(long, long)</a></code>
+     * @return {@link java.lang.Math#min(long, long)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">min(long, long)</a></code>
+     * 
+     * @see java.lang.Math#min(long, long)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/integerMax.html">min(long, long)</a></code>
+     */
+   @OpenCLMapping(mapTo = "min") protected long min(long n1, long n2) {
+      return Math.min(n1, n2);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#log(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/log.html">log(float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f value to delegate to {@link java.lang.Math#log(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/log.html">log(float)</a></code>
+     * @return {@link java.lang.Math#log(double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/log.html">log(float)</a></code>
+     * 
+     * @see java.lang.Math#log(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/log.html">log(float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "log") protected float log(float _f) {
+      return (float) Math.log(_f);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#log(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/log.html">log(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d value to delegate to {@link java.lang.Math#log(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/log.html">log(double)</a></code>
+     * @return {@link java.lang.Math#log(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/log.html">log(double)</a></code>
+     * 
+     * @see java.lang.Math#log(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/log.html">log(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "log") protected double log(double _d) {
+      return Math.log(_d);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#pow(double, double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/pow.html">pow(float, float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f1 value to delegate to first argument of {@link java.lang.Math#pow(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/pow.html">pow(float, float)</a></code>
+     * @param _f2 value to delegate to second argument of {@link java.lang.Math#pow(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/pow.html">pow(float, float)</a></code>
+     * @return {@link java.lang.Math#pow(double, double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/pow.html">pow(float, float)</a></code>
+     * 
+     * @see java.lang.Math#pow(double, double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/pow.html">pow(float, float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "pow") protected float pow(float _f1, float _f2) {
+      return (float) Math.pow(_f1, _f2);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#pow(double, double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/pow.html">pow(double, double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d1 value to delegate to first argument of {@link java.lang.Math#pow(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/pow.html">pow(double, double)</a></code>
+     * @param _d2 value to delegate to second argument of {@link java.lang.Math#pow(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/pow.html">pow(double, double)</a></code>
+     * @return {@link java.lang.Math#pow(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/pow.html">pow(double, double)</a></code>
+     * 
+     * @see java.lang.Math#pow(double, double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/pow.html">pow(double, double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "pow") protected double pow(double _d1, double _d2) {
+      return Math.pow(_d1, _d2);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#IEEEremainder(double, double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/remainder.html">remainder(float, float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f1 value to delegate to first argument of {@link java.lang.Math#IEEEremainder(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/remainder.html">remainder(float, float)</a></code>
+     * @param _f2 value to delegate to second argument of {@link java.lang.Math#IEEEremainder(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/remainder.html">remainder(float, float)</a></code>
+     * @return {@link java.lang.Math#IEEEremainder(double, double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/remainder.html">remainder(float, float)</a></code>
+     * 
+     * @see java.lang.Math#IEEEremainder(double, double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/remainder.html">remainder(float, float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "remainder") protected float IEEEremainder(float _f1, float _f2) {
+      return (float) Math.IEEEremainder(_f1, _f2);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#IEEEremainder(double, double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/remainder.html">remainder(double, double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d1 value to delegate to first argument of {@link java.lang.Math#IEEEremainder(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/remainder.html">remainder(double, double)</a></code>
+     * @param _d2 value to delegate to second argument of {@link java.lang.Math#IEEEremainder(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/remainder.html">remainder(double, double)</a></code>
+     * @return {@link java.lang.Math#IEEEremainder(double, double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/remainder.html">remainder(double, double)</a></code>
+     * 
+     * @see java.lang.Math#IEEEremainder(double, double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/remainder.html">remainder(double, double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "remainder") protected double IEEEremainder(double _d1, double _d2) {
+      return Math.IEEEremainder(_d1, _d2);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#toRadians(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/radians.html">radians(float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f value to delegate to {@link java.lang.Math#toRadians(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/radians.html">radians(float)</a></code>
+     * @return {@link java.lang.Math#toRadians(double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/radians.html">radians(float)</a></code>
+     * 
+     * @see java.lang.Math#toRadians(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/radians.html">radians(float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "radians") protected float toRadians(float _f) {
+      return (float) Math.toRadians(_f);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#toRadians(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/radians.html">radians(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d value to delegate to {@link java.lang.Math#toRadians(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/radians.html">radians(double)</a></code>
+     * @return {@link java.lang.Math#toRadians(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/radians.html">radians(double)</a></code>
+     * 
+     * @see java.lang.Math#toRadians(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/radians.html">radians(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "radians") protected double toRadians(double _d) {
+      return Math.toRadians(_d);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#toDegrees(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/degrees.html">degrees(float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f value to delegate to {@link java.lang.Math#toDegrees(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/degrees.html">degrees(float)</a></code>
+     * @return {@link java.lang.Math#toDegrees(double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/degrees.html">degrees(float)</a></code>
+     * 
+     * @see java.lang.Math#toDegrees(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/degrees.html">degrees(float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "degrees") protected float toDegrees(float _f) {
+      return (float) Math.toDegrees(_f);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#toDegrees(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/degrees.html">degrees(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d value to delegate to {@link java.lang.Math#toDegrees(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/degrees.html">degrees(double)</a></code>
+     * @return {@link java.lang.Math#toDegrees(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/degrees.html">degrees(double)</a></code>
+     * 
+     * @see java.lang.Math#toDegrees(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/degrees.html">degrees(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "degrees") protected double toDegrees(double _d) {
+      return Math.toDegrees(_d);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#rint(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/rint.html">rint(float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f value to delegate to {@link java.lang.Math#rint(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/rint.html">rint(float)</a></code>
+     * @return {@link java.lang.Math#rint(double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/rint.html">rint(float)</a></code>
+     * 
+     * @see java.lang.Math#rint(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/rint.html">rint(float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "rint") protected float rint(float _f) {
+      return (float) Math.rint(_f);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#rint(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/rint.html">rint(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d value to delegate to {@link java.lang.Math#rint(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/rint.html">rint(double)</a></code>
+     * @return {@link java.lang.Math#rint(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/rint.html">rint(double)</a></code>
+     * 
+     * @see java.lang.Math#rint(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/rint.html">rint(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "rint") protected double rint(double _d) {
+      return Math.rint(_d);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#round(float)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/round.html">round(float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f value to delegate to {@link java.lang.Math#round(float)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/round.html">round(float)</a></code>
+     * @return {@link java.lang.Math#round(float)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/round.html">round(float)</a></code>
+     * 
+     * @see java.lang.Math#round(float)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/round.html">round(float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "round") protected int round(float _f) {
+      return Math.round(_f);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#round(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/round.html">round(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d value to delegate to {@link java.lang.Math#round(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/round.html">round(double)</a></code>
+     * @return {@link java.lang.Math#round(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/round.html">round(double)</a></code>
+     * 
+     * @see java.lang.Math#round(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/round.html">round(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "round") protected long round(double _d) {
+      return Math.round(_d);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#sin(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sin.html">sin(float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f value to delegate to {@link java.lang.Math#sin(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sin.html">sin(float)</a></code>
+     * @return {@link java.lang.Math#sin(double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sin.html">sin(float)</a></code>
+     * 
+     * @see java.lang.Math#sin(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sin.html">sin(float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "sin") protected float sin(float _f) {
+      return (float) Math.sin(_f);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#sin(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sin.html">sin(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d value to delegate to {@link java.lang.Math#sin(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sin.html">sin(double)</a></code>
+     * @return {@link java.lang.Math#sin(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sin.html">sin(double)</a></code>
+     * 
+     * @see java.lang.Math#sin(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sin.html">sin(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "sin") protected double sin(double _d) {
+      return Math.sin(_d);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#sqrt(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sqrt.html">sqrt(float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f value to delegate to {@link java.lang.Math#sqrt(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sqrt.html">sqrt(float)</a></code>
+     * @return {@link java.lang.Math#sqrt(double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sqrt.html">sqrt(float)</a></code>
+     * 
+     * @see java.lang.Math#sqrt(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sqrt.html">sqrt(float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "sqrt") protected float sqrt(float _f) {
+      return (float) Math.sqrt(_f);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#sqrt(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sqrt.html">sqrt(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d value to delegate to {@link java.lang.Math#sqrt(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sqrt.html">sqrt(double)</a></code>
+     * @return {@link java.lang.Math#sqrt(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sqrt.html">sqrt(double)</a></code>
+     * 
+     * @see java.lang.Math#sqrt(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sqrt.html">sqrt(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "sqrt") protected double sqrt(double _d) {
+      return Math.sqrt(_d);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#tan(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/tan.html">tan(float)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f value to delegate to {@link java.lang.Math#tan(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/tan.html">tan(float)</a></code>
+     * @return {@link java.lang.Math#tan(double)} casted to float/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/tan.html">tan(float)</a></code>
+     * 
+     * @see java.lang.Math#tan(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/tan.html">tan(float)</a></code>
+     */
+   @OpenCLMapping(mapTo = "tan") protected float tan(float _f) {
+      return (float) Math.tan(_f);
+   }
+
+   /**
+    * Delegates to either {@link java.lang.Math#tan(double)} (Java) or <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/tan.html">tan(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d value to delegate to {@link java.lang.Math#tan(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/tan.html">tan(double)</a></code>
+     * @return {@link java.lang.Math#tan(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/tan.html">tan(double)</a></code>
+     * 
+     * @see java.lang.Math#tan(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/tan.html">tan(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "tan") protected double tan(double _d) {
+      return Math.tan(_d);
+   }
+
+   // the following rsqrt and native_sqrt and native_rsqrt don't exist in java Math
+   // but added them here for nbody testing, not sure if we want to expose them
+   /**
+    * Computes  inverse square root using {@link java.lang.Math#sqrt(double)} (Java) or delegates to <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sqrt.html">rsqrt(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _f value to delegate to {@link java.lang.Math#sqrt(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sqrt.html">rsqrt(double)</a></code>
+     * @return <code>( 1.0f / {@link java.lang.Math#sqrt(double)} casted to float )</code>/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sqrt.html">rsqrt(double)</a></code>
+     * 
+     * @see java.lang.Math#sqrt(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sqrt.html">rsqrt(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "rsqrt") protected float rsqrt(float _f) {
+      return (1.0f / (float) Math.sqrt(_f));
+   }
+
+   /**
+    * Computes  inverse square root using {@link java.lang.Math#sqrt(double)} (Java) or delegates to <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sqrt.html">rsqrt(double)</a></code> (OpenCL).
+     * 
+     * User should note the differences in precision between Java and OpenCL's implementation of arithmetic functions to determine whether the difference in precision is acceptable.
+     * 
+     * @param _d value to delegate to {@link java.lang.Math#sqrt(double)}/<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sqrt.html">rsqrt(double)</a></code>
+     * @return <code>( 1.0f / {@link java.lang.Math#sqrt(double)} )</code> /<code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sqrt.html">rsqrt(double)</a></code>
+     * 
+     * @see java.lang.Math#sqrt(double)
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/sqrt.html">rsqrt(double)</a></code>
+     */
+   @OpenCLMapping(mapTo = "rsqrt") protected double rsqrt(double _d) {
+      return (1.0 / Math.sqrt(_d));
+   }
+
+   @SuppressWarnings("unused") @OpenCLMapping(mapTo = "native_sqrt") private float native_sqrt(float _f) {
+      int j = Float.floatToIntBits(_f);
+      j = (1 << 29) + (j >> 1) - (1 << 22) - 0x4c00;
+      return (Float.intBitsToFloat(j));
+      // could add more precision using one iteration of newton's method, use the following
+   }
+
+   @SuppressWarnings("unused") @OpenCLMapping(mapTo = "native_rsqrt") private float native_rsqrt(float _f) {
+      int j = Float.floatToIntBits(_f);
+      j = 0x5f3759df - (j >> 1);
+      float x = (Float.intBitsToFloat(j));
+      return x;
+      // if want more precision via one iteration of newton's method, use the following
+      // float fhalf = 0.5f*_f;
+      // return (x *(1.5f - fhalf * x * x));
+   }
+
+   // Hacked from AtomicIntegerArray.getAndAdd(i, delta)
+   /**
+    * Atomically adds <code>_delta</code> value to <code>_index</code> element of array <code>_arr</code> (Java) or delegates to <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atomic_add.html">atomic_add(volatile int*, int)</a></code> (OpenCL).
+     * 
+     * 
+     * @param _arr array for which an element value needs to be atomically incremented by <code>_delta</code>
+     * @param _index index of the <code>_arr</code> array that needs to be atomically incremented by <code>_delta</code>
+     * @param _delta value by which <code>_index</code> element of <code>_arr</code> array needs to be atomically incremented  
+     * @return previous value of <code>_index</code> element of <code>_arr</code> array
+     * 
+     * @see <code><a href="http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/atomic_add.html">atomic_add(volatile int*, int)</a></code>
+     */
+   @OpenCLMapping(atomic32 = true) protected int atomicAdd(int[] _arr, int _index, int _delta) {
+
+      if (!Config.disableUnsafe) {
+         return UnsafeWrapper.atomicAdd(_arr, _index, _delta);
+      } else {
+         synchronized (_arr) {
+            int previous = _arr[_index];
+            _arr[_index] += _delta;
+            return previous;
+         }
+      }
+   }
+
+   /**
+    * Wait for all kernels in the current group to rendezvous at this call before continuing execution.
+    * 
+    * @annotion Experimental
+    */
+
+   @OpenCLDelegate @Annotations.Experimental protected final void localBarrier() {
+      try {
+         localBarrier.await();
+      } catch (InterruptedException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (BrokenBarrierException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+   }
+
+   /**
+    * Wait for all kernels in the current group to rendezvous at this call before continuing execution.
+    * 
+    * 
+    * Java version is identical to localBarrier()
+    * 
+    * @annotion Experimental
+    */
+
+   @OpenCLDelegate @Annotations.Experimental protected final void globalBarrier() {
+      try {
+         localBarrier.await();
+      } catch (InterruptedException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (BrokenBarrierException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+   }
+
+   final void setSizes(int _globalSize, int _localSize) {
+      localSize = _localSize;
+      globalSize = _globalSize;
+
+   }
+
+   private KernelRunner kernelRunner = null;
+
+   KernelRunner getKernelRunner() {
+      return kernelRunner;
+   }
+
+   /**
+    * Determine the execution time of the previous Kernel.execute(range) call.
+    * 
+    * Note that for the first call this will include the conversion time. 
+    * 
+    * @return The time spent executing the kernel (ms) 
+    * 
+    * @see getConversionTime();
+    * @see getAccumulatedExectutionTime();
+    * 
+    */
+   public synchronized long getExecutionTime() {
+      return (kernelRunner.getExecutionTime());
+   }
+
+   /**
+    * Determine the total execution time of all previous Kernel.execute(range) calls.
+    * 
+    * Note that this will include the initial conversion time. 
+    * 
+    * @return The total time spent executing the kernel (ms) 
+    * 
+    * @see getExecutionTime();
+    * @see getConversionTime();
+    * 
+    */
+   public synchronized long getAccumulatedExecutionTime() {
+      return (kernelRunner.getAccumulatedExecutionTime());
+   }
+
+   /**
+    * Determine the time taken to convert bytecode to OpenCL for first Kernel.execute(range) call.
+    * @return The time spent preparing the kernel for execution using GPU
+    * 
+    * @see getExecutionTime();
+    * @see getAccumulatedExectutionTime();
+    */
+   public synchronized long getConversionTime() {
+      return (kernelRunner.getConversionTime());
+   }
+
+   /**
+    * Start execution of <code>globalSize</code> kernels.
+    * <p>
+    * When <code>kernel.execute(globalSize)</code> is invoked, Aparapi will schedule the execution of <code>globalSize</code> kernels. If the execution mode is GPU then 
+    * the kernels will execute as OpenCL code on the GPU device. Otherwise, if the mode is JTP, the kernels will execute as a pool of Java threads on the CPU. 
+    * <p>
+    * @param _globalSize The number of Kernels that we would like to initiate.
+    * @returnThe Kernel instance (this) so we can chain calls to put(arr).execute(range).get(arr)
+    * 
+    */
+   public synchronized Kernel execute(int _globalSize) {
+      return (execute(_globalSize, 1));
+   }
+
+   /**
+    * Start execution of <code>_passes</code> iterations of <code>globalSize</code> kernels.
+    * <p>
+    * When <code>kernel.execute(globalSize, passes)</code> is invoked, Aparapi will schedule the execution of <code>globalSize</code> kernels. If the execution mode is GPU then 
+    * the kernels will execute as OpenCL code on the GPU device. Otherwise, if the mode is JTP, the kernels will execute as a pool of Java threads on the CPU. 
+    * <p>
+    * @param _globalSize The number of Kernels that we would like to initiate.
+    * @param _passes The number of passes to make
+    * @return The Kernel instance (this) so we can chain calls to put(arr).execute(range).get(arr)
+    * 
+    */
+   public synchronized Kernel execute(int _globalSize, int _passes) {
+      return (execute("run", _globalSize, _passes));
+   }
+
+   /**
+    * Start execution of <code>globalSize</code> kernels for the given entrypoint.
+    * <p>
+    * When <code>kernel.execute("entrypoint", globalSize)</code> is invoked, Aparapi will schedule the execution of <code>globalSize</code> kernels. If the execution mode is GPU then 
+    * the kernels will execute as OpenCL code on the GPU device. Otherwise, if the mode is JTP, the kernels will execute as a pool of Java threads on the CPU. 
+    * <p>
+    * @param _entrypoint is the name of the method we wish to use as the entrypoint to the kernel
+    * @param _globalSize The number of Kernels that we would like to initiate.
+    * @return The Kernel instance (this) so we can chain calls to put(arr).execute(range).get(arr)
+    * 
+    */
+   public synchronized Kernel execute(Entry _entry, int _globalSize) {
+      if (kernelRunner == null) {
+         kernelRunner = new KernelRunner(this);
+
+      }
+      return (kernelRunner.execute(_entry, _globalSize, 1));
+   }
+
+   /**
+    * Start execution of <code>globalSize</code> kernels for the given entrypoint.
+    * <p>
+    * When <code>kernel.execute("entrypoint", globalSize)</code> is invoked, Aparapi will schedule the execution of <code>globalSize</code> kernels. If the execution mode is GPU then 
+    * the kernels will execute as OpenCL code on the GPU device. Otherwise, if the mode is JTP, the kernels will execute as a pool of Java threads on the CPU. 
+    * <p>
+    * @param _entrypoint is the name of the method we wish to use as the entrypoint to the kernel
+    * @param _globalSize The number of Kernels that we would like to initiate.
+    * @return The Kernel instance (this) so we can chain calls to put(arr).execute(range).get(arr)
+    * 
+    */
+   public synchronized Kernel execute(String _entrypoint, int _globalSize) {
+      return (execute(_entrypoint, _globalSize, 1));
+
+   }
+
+   /**
+    * Start execution of <code>globalSize</code> kernels for the given entrypoint.
+    * <p>
+    * When <code>kernel.execute("entrypoint", globalSize)</code> is invoked, Aparapi will schedule the execution of <code>globalSize</code> kernels. If the execution mode is GPU then 
+    * the kernels will execute as OpenCL code on the GPU device. Otherwise, if the mode is JTP, the kernels will execute as a pool of Java threads on the CPU. 
+    * <p>
+    * @param _entrypoint is the name of the method we wish to use as the entrypoint to the kernel
+    * @param _globalSize The number of Kernels that we would like to initiate.
+    * @return The Kernel instance (this) so we can chain calls to put(arr).execute(range).get(arr)
+    * 
+    */
+   public synchronized Kernel execute(String _entrypoint, int _globalSize, int _passes) {
+      if (kernelRunner == null) {
+         kernelRunner = new KernelRunner(this);
+
+      }
+      return (kernelRunner.execute(_entrypoint, _globalSize, _passes));
+
+   }
+
+   /**
+    * Release any resources associated with this Kernel.
+    * <p>
+    * When the execution mode is <code>CPU</code> or <code>GPU</code>, Aparapi stores some OpenCL resources in a data structure associated with the kernel instance.  The 
+    * <code>dispose()</code> method must be called to release these resources. 
+    * <p>
+    * If <code>execute(int _globalSize)</code> is called after <code>dispose()</code> is called the results are undefined.  
+    */
+   public synchronized void dispose() {
+      if (kernelRunner != null) {
+         kernelRunner.dispose();
+         kernelRunner = null;
+      }
+
+   }
+
+   /**
+    * Return the current execution mode.  
+    * 
+    * Before a Kernel executes, this return value will be the execution mode as determined by the setting of 
+    * the EXECUTION_MODE enumeration. By default, this setting is either <b>GPU</b> 
+    * if OpenCL is available on the target system, or <b>JTP</b> otherwise. This default setting can be
+    * changed by calling setExecutionMode(). 
+    * 
+    * <p>
+    * After a Kernel executes, the return value will be the mode in which the Kernel actually executed.
+    * 
+    * @return The current execution mode.
+    * 
+    * @see #setExecutionMode(EXECUTION_MODE)
+    */
+   public EXECUTION_MODE getExecutionMode() {
+      return (executionMode);
+   }
+
+   /**
+    * Set the execution mode. 
+    * <p>
+    * This should be regarded as a request. The real mode will be determined at runtime based on the availability of OpenCL and the characteristics of the workload.
+    * 
+    * @param _executionMode the requested execution mode.
+    * 
+    * @see #getExecutionMode()
+    */
+   public void setExecutionMode(EXECUTION_MODE _executionMode) {
+      executionMode = _executionMode;
+   }
+
+   void setFallbackExecutionMode() {
+      executionMode = EXECUTION_MODE.getFallbackExecutionMode();
+
+   }
+
+   final static Map<String, String> typeToLetterMap = new HashMap<String, String>();
+
+   static {
+      // only primitive types for now
+      typeToLetterMap.put("double", "D");
+      typeToLetterMap.put("float", "F");
+      typeToLetterMap.put("int", "I");
+      typeToLetterMap.put("long", "J");
+      typeToLetterMap.put("boolean", "Z");
+      typeToLetterMap.put("byte", "B");
+      typeToLetterMap.put("char", "C");
+      typeToLetterMap.put("short", "S");
+      typeToLetterMap.put("void", "V");
+   }
+
+   private static String descriptorToReturnTypeLetter(String desc) {
+      // find the letter after the closed parenthesis
+      return desc.substring(desc.lastIndexOf(')') + 1);
+   }
+
+   private static String getReturnTypeLetter(Method meth) {
+      Class<?> retClass = meth.getReturnType();
+      String strRetClass = retClass.toString();
+      String mapping = typeToLetterMap.get(strRetClass);
+      // System.out.println("strRetClass = <" + strRetClass + ">, mapping = " + mapping);
+      return mapping;
+   }
+
+   static String getMappedMethodName(MethodReferenceEntry _methodReferenceEntry) {
+      String mappedName = null;
+      String name = _methodReferenceEntry.getNameAndTypeEntry().getNameUTF8Entry().getUTF8();
+      for (Method kernelMethod : Kernel.class.getDeclaredMethods()) {
+         if (kernelMethod.isAnnotationPresent(OpenCLMapping.class)) {
+            // ultimately, need a way to constrain this based upon signature (to disambiguate abs(float) from abs(int);
+            // for Alpha, we will just disambiguate based on the return type
+            if (false) {
+               System.out.println("kernelMethod is ... " + kernelMethod.toGenericString());
+               System.out.println("returnType = " + kernelMethod.getReturnType());
+               System.out.println("returnTypeLetter = " + getReturnTypeLetter(kernelMethod));
+               System.out.println("kernelMethod getName = " + kernelMethod.getName());
+               System.out.println("methRefName = " + name + " descriptor = "
+                     + _methodReferenceEntry.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8());
+               System.out
+                     .println("descToReturnTypeLetter = "
+                           + descriptorToReturnTypeLetter(_methodReferenceEntry.getNameAndTypeEntry().getDescriptorUTF8Entry()
+                                 .getUTF8()));
+            }
+            if (_methodReferenceEntry.getNameAndTypeEntry().getNameUTF8Entry().getUTF8().equals(kernelMethod.getName())
+                  && descriptorToReturnTypeLetter(_methodReferenceEntry.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8())
+                        .equals(getReturnTypeLetter(kernelMethod))) {
+               OpenCLMapping annotation = kernelMethod.getAnnotation(OpenCLMapping.class);
+               String mapTo = annotation.mapTo();
+               if (!mapTo.equals("")) {
+                  mappedName = mapTo;
+                  // System.out.println("mapTo = " + mapTo);
+               }
+            }
+         }
+      }
+      // System.out.println("... in getMappedMethodName, returning = " + mappedName);
+      return (mappedName);
+   }
+
+   static boolean isMappedMethod(MethodReferenceEntry methodReferenceEntry) {
+      boolean isMapped = false;
+      for (Method kernelMethod : Kernel.class.getDeclaredMethods()) {
+         if (kernelMethod.isAnnotationPresent(OpenCLMapping.class)) {
+            if (methodReferenceEntry.getNameAndTypeEntry().getNameUTF8Entry().getUTF8().equals(kernelMethod.getName())) {
+
+               // well they have the same name ;) 
+               isMapped = true;
+            }
+         }
+      }
+      return (isMapped);
+   }
+
+   static boolean isOpenCLDelegateMethod(MethodReferenceEntry methodReferenceEntry) {
+      boolean isMapped = false;
+      for (Method kernelMethod : Kernel.class.getDeclaredMethods()) {
+         if (kernelMethod.isAnnotationPresent(OpenCLDelegate.class)) {
+            if (methodReferenceEntry.getNameAndTypeEntry().getNameUTF8Entry().getUTF8().equals(kernelMethod.getName())) {
+
+               // well they have the same name ;) 
+               isMapped = true;
+            }
+         }
+      }
+      return (isMapped);
+   }
+
+   static boolean usesAtomic32(MethodReferenceEntry methodReferenceEntry) {
+      for (Method kernelMethod : Kernel.class.getDeclaredMethods()) {
+         if (kernelMethod.isAnnotationPresent(OpenCLMapping.class)) {
+            if (methodReferenceEntry.getNameAndTypeEntry().getNameUTF8Entry().getUTF8().equals(kernelMethod.getName())) {
+               OpenCLMapping annotation = kernelMethod.getAnnotation(OpenCLMapping.class);
+               return annotation.atomic32();
+            }
+         }
+      }
+      return (false);
+   }
+
+   // For alpha release atomic64 is not supported
+   static boolean usesAtomic64(MethodReferenceEntry methodReferenceEntry) {
+      //for (java.lang.reflect.Method kernelMethod : Kernel.class.getDeclaredMethods()) {
+      //   if (kernelMethod.isAnnotationPresent(Kernel.OpenCLMapping.class)) {
+      //      if (methodReferenceEntry.getNameAndTypeEntry().getNameUTF8Entry().getUTF8().equals(kernelMethod.getName())) {
+      //         OpenCLMapping annotation = kernelMethod.getAnnotation(Kernel.OpenCLMapping.class);
+      //           return annotation.atomic64();
+      //      }
+      //   }
+      //}
+      return (false);
+   }
+
+   void setLocalSize(int _localSize) {
+      localSize = _localSize;
+
+   }
+
+   // the flag useNullForLocalSize is useful for testing that what we compute for localSize is what OpenCL
+   // would also compute if we passed in null.  In non-testing mode, we just call execute with the
+   // same localSize that we computed in getLocalSizeJNI.  We don't want do publicize these of course.
+   // GRF we can't access this from test classes without exposing in in javadoc so I left the flag but made the test/set of the flag reflectively
+   boolean useNullForLocalSize = false;
+
+   // Explicit memory management API's follow
+
+   /**
+    * For dev purposes (we should remove this for production) allow us to define that this Kernel uses explicit memory management
+    * @param _explicit (true if we want explicit memory management)
+    */
+   public void setExplicit(boolean _explicit) {
+      if (kernelRunner == null) {
+         kernelRunner = new KernelRunner(this);
+
+      }
+      kernelRunner.setExplicit(_explicit);
+   }
+
+   /**
+    * For dev purposes (we should remove this for production) determine whether this Kernel uses explicit memory management
+    * @return  (true if we kernel is using explicit memory management)
+    */
+   public boolean isExplicit() {
+      if (kernelRunner == null) {
+         kernelRunner = new KernelRunner(this);
+
+      }
+      return (kernelRunner.isExplicit());
+   }
+
+   /**
+    * Tag this array so that it is explicitly enqueued before the kernel is executed
+    * @param array
+    * @return This kernel so that we can use the 'fluent' style API
+    */
+   public Kernel put(long[] array) {
+      if (kernelRunner == null) {
+         kernelRunner = new KernelRunner(this);
+
+      }
+      kernelRunner.put(array);
+      return (this);
+   }
+
+   /**
+    * Tag this array so that it is explicitly enqueued before the kernel is executed
+    * @param array
+    * @return This kernel so that we can use the 'fluent' style API
+    */
+   public Kernel put(double[] array) {
+      if (kernelRunner == null) {
+         kernelRunner = new KernelRunner(this);
+
+      }
+      kernelRunner.put(array);
+      return (this);
+   }
+
+   /**
+    * Tag this array so that it is explicitly enqueued before the kernel is executed
+    * @param array
+    * @return This kernel so that we can use the 'fluent' style API
+    */
+   public Kernel put(float[] array) {
+      if (kernelRunner == null) {
+         kernelRunner = new KernelRunner(this);
+
+      }
+      kernelRunner.put(array);
+      return (this);
+   }
+
+   /**
+    * Tag this array so that it is explicitly enqueued before the kernel is executed
+    * @param array
+    * @return This kernel so that we can use the 'fluent' style API
+    */
+   public Kernel put(int[] array) {
+      if (kernelRunner == null) {
+         kernelRunner = new KernelRunner(this);
+
+      }
+      kernelRunner.put(array);
+      return (this);
+   }
+
+   /**
+    * Tag this array so that it is explicitly enqueued before the kernel is executed
+    * @param array
+    * @return This kernel so that we can use the 'fluent' style API
+    */
+   public Kernel put(byte[] array) {
+      if (kernelRunner == null) {
+         kernelRunner = new KernelRunner(this);
+
+      }
+      kernelRunner.put(array);
+      return (this);
+   }
+
+   /**
+    * Enqueue a request to return this buffer from the GPU. This method blocks until the array is available. 
+    * @param array
+    * @return This kernel so that we can use the 'fluent' style API
+    */
+   public Kernel get(long[] array) {
+      if (kernelRunner == null) {
+         kernelRunner = new KernelRunner(this);
+
+      }
+      kernelRunner.get(array);
+      return (this);
+   }
+
+   /**
+    * Enqueue a request to return this buffer from the GPU. This method blocks until the array is available. 
+    * @param array
+    * @return This kernel so that we can use the 'fluent' style API
+    */
+   public Kernel get(double[] array) {
+      if (kernelRunner == null) {
+         kernelRunner = new KernelRunner(this);
+
+      }
+      kernelRunner.get(array);
+      return (this);
+   }
+
+   /**
+    * Enqueue a request to return this buffer from the GPU. This method blocks until the array is available. 
+    * @param array
+    * @return This kernel so that we can use the 'fluent' style API
+    */
+   public Kernel get(float[] array) {
+      if (kernelRunner == null) {
+         kernelRunner = new KernelRunner(this);
+
+      }
+      kernelRunner.get(array);
+      return (this);
+   }
+
+   /**
+    * Enqueue a request to return this buffer from the GPU. This method blocks until the array is available. 
+    * @param array
+    * @return This kernel so that we can use the 'fluent' style API
+    */
+   public Kernel get(int[] array) {
+      if (kernelRunner == null) {
+         kernelRunner = new KernelRunner(this);
+
+      }
+      kernelRunner.get(array);
+      return (this);
+   }
+
+   /**
+    * Enqueue a request to return this buffer from the GPU. This method blocks until the array is available. 
+    * @param array
+    * @return This kernel so that we can use the 'fluent' style API
+    */
+   public Kernel get(byte[] array) {
+      if (kernelRunner == null) {
+         kernelRunner = new KernelRunner(this);
+
+      }
+      kernelRunner.get(array);
+      return (this);
+   }
+
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/KernelRunner.java b/com.amd.aparapi/src/java/com/amd/aparapi/KernelRunner.java
new file mode 100644
index 00000000..1d9ac0a4
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/KernelRunner.java
@@ -0,0 +1,1430 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.amd.aparapi.InstructionSet.TypeSpec;
+import com.amd.aparapi.Kernel.EXECUTION_MODE;
+
+/**
+ * The class is responsible for executing <code>Kernel</code> implementations. <br/>
+ * 
+ * The <code>KernelRunner</code> is the real workhorse for Aparapi.  Each <code>Kernel</code> instance creates a single
+ * <code>KernelRunner</code> to encapsulate state and to help coordinate interactions between the <code>Kernel</code> 
+ * and it's execution logic.<br/>
+ * 
+ * The <code>KernelRunner</code> is created <i>lazily</i> as a result of calling <code>Kernel.execute()</code>. A this 
+ * time the <code>ExecutionMode</code> is consulted to determine the default requested mode.  This will dictate how 
+ * the <code>KernelRunner</code> will attempt to execute the <code>Kernel</code>
+ *   
+ * @see com.amd.aparapi.Kernel#execute(int _globalSize)
+ * 
+ * @author gfrost
+ *
+ */
+class KernelRunner{
+   public @interface UsedByJNICode {
+
+   }
+
+   private static Logger logger = Logger.getLogger(Config.getLoggerName());
+
+   /**
+    * This 'bit' indicates that a particular <code>KernelArg</code> represents a <code>boolean</code> type (array or primitive). 
+    * 
+   * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_BOOLEAN = 1 << 0;
+
+   /**
+    * This 'bit' indicates that a particular <code>KernelArg</code> represents a <code>byte</code> type (array or primitive). 
+    * 
+   * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_BYTE = 1 << 1;
+
+   /**
+    * This 'bit' indicates that a particular <code>KernelArg</code> represents a <code>float</code> type (array or primitive). 
+    * 
+   * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_FLOAT = 1 << 2;
+
+   /**
+    * This 'bit' indicates that a particular <code>KernelArg</code> represents a <code>int</code> type (array or primitive). 
+    * 
+   * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_INT = 1 << 3;
+
+   /**
+    * This 'bit' indicates that a particular <code>KernelArg</code> represents a <code>double</code> type (array or primitive). 
+    * 
+   * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_DOUBLE = 1 << 4;
+
+   /**
+    * This 'bit' indicates that a particular <code>KernelArg</code> represents a <code>long</code> type (array or primitive). 
+    * 
+   * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_LONG = 1 << 5;
+
+   /**
+    * TODO:
+    * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_SHORT = 1 << 6;
+
+   /**
+    * This 'bit' indicates that a particular <code>KernelArg</code> represents an array.<br/>
+    *   So <code>ARG_ARRAY|ARG_INT</code> tells us this arg is an array of <code>int</code>.
+    * 
+   * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_ARRAY = 1 << 7;
+
+   /**
+    * This 'bit' indicates that a particular <code>KernelArg</code> represents a primitive (non array).<br/>
+    *   So <code>ARG_PRIMITIVE|ARG_INT</code> tells us this arg is a primitive <code>int</code>.
+    * 
+   * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_PRIMITIVE = 1 << 8;
+
+   /**
+    * This 'bit' indicates that a particular <code>KernelArg</code> is read by the Kernel (note from the Kernel's point of view).<br/>
+    *   So <code>ARG_ARRAY|ARG_INT|ARG_READ</code> tells us this arg is an array of int's that are read by the kernel.
+    * 
+   * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_READ = 1 << 9;
+
+   /**
+    * This 'bit' indicates that a particular <code>KernelArg</code> is mutated by the Kernel (note from the Kernel's point of view).<br/>
+    *   So <code>ARG_ARRAY|ARG_INT|ARG_WRITE</code> tells us this arg is an array of int's that we expect the kernel to mutate.
+    * 
+   * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_WRITE = 1 << 10;
+
+   /**
+    * This 'bit' indicates that a particular <code>KernelArg</code> resides in local memory in the generated OpenCL code.<br/>
+    * 
+   * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.annotations.Experimental
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @Annotations.Experimental @UsedByJNICode public static final int ARG_LOCAL = 1 << 11;
+
+   /**
+    * This 'bit' indicates that a particular <code>KernelArg</code> resides in global memory in the generated OpenCL code.<br/>
+    * 
+   * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.annotations.Experimental
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @Annotations.Experimental @UsedByJNICode public static final int ARG_GLOBAL = 1 << 12;
+
+   /**
+    * This 'bit' indicates that a particular <code>KernelArg</code> resides in constant memory in the generated OpenCL code.<br/>
+    * 
+    * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.annotations.Experimental
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @Annotations.Experimental @UsedByJNICode public static final int ARG_CONSTANT = 1 << 13;
+
+   /**
+    * This 'bit' indicates that a particular <code>KernelArg</code> has it's length reference, in which case a synthetic arg is passed (name mangled) to the OpenCL kernel.<br/>
+    * 
+    * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_ARRAYLENGTH = 1 << 14;
+
+   /**
+    * TODO:
+    * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_APARAPI_BUF = 1 << 15;
+
+   /**
+    * This 'bit' indicates that the arg has been explicitly marked for reading
+    * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_EXPLICIT = 1 << 16;
+
+   /**
+    * This 'bit' indicates that the arg has been explicitly marked for writing
+    * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_EXPLICIT_WRITE = 1 << 17;
+
+   /**
+    * TODO:
+    * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_OBJ_ARRAY_STRUCT = 1 << 18;
+
+   /**
+    * TODO:
+    * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_APARAPI_BUF_HAS_ARRAY = 1 << 19;
+
+   /**
+    * TODO:
+    * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.KernelRunner.KernelArg
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int ARG_APARAPI_BUF_IS_DIRECT = 1 << 20;
+
+   static final String CL_KHR_FP64 = "cl_khr_fp64";
+
+   static final String CL_AMD_FP64 = "cl_amd_fp64";
+
+   static final String CL_KHR_SELECT_FPROUNDING_MODE = "cl_khr_select_fprounding_mode";
+
+   static final String CL_KHR_GLOBAL_INT32_BASE_ATOMICS = "cl_khr_global_int32_base_atomics";
+
+   static final String CL_KHR_GLOBAL_INT32_EXTENDED_ATOMICS = "cl_khr_global_int32_extended_atomics";
+
+   static final String CL_KHR_LOCAL_INT32_BASE_ATOMICS = "cl_khr_local_int32_base_atomics";
+
+   static final String CL_KHR_LOCAL_INT32_EXTENDED_ATOMICS = "cl_khr_local_int32_extended_atomics";
+
+   static final String CL_KHR_INT64_BASE_ATOMICS = "cl_khr_int64_base_atomics";
+
+   static final String CL_KHR_INT64_EXTENDED_ATOMICS = "cl_khr_int64_extended_atomics";
+
+   static final String CL_KHR_3D_IMAGE_WRITES = "cl_khr_3d_image_writes";
+
+   static final String CL_KHR_BYTE_ADDRESSABLE_SUPPORT = "cl_khr_byte_addressable_store";
+
+   static final String CL_KHR_FP16 = "cl_khr_fp16";
+
+   static final String CL_KHR_GL_SHARING = "cl_khr_gl_sharing";
+
+   /**
+    * This 'bit' indicates that we wish to enable profiling from the JNI code. 
+    * 
+   * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int JNI_FLAG_ENABLE_PROFILING = 1 << 0;
+
+   /**
+    * This 'bit' indicates that we want to execute on the GPU. 
+    * 
+     * 
+    * Be careful changing final constants starting with JNI.<br/>
+    * 
+     * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * 
+    * @author gfrost
+    */
+   @UsedByJNICode public static final int JNI_FLAG_USE_GPU = 1 << 1;
+
+   /**
+    * This 'bit' indicates that we wish to enable verbose JNI layer messages to stderr.<br/>
+    * 
+    * @see com.amd.aparapi.annotations.UsedByJNICode
+    * @see com.amd.aparapi.annotations.Experimental
+    * 
+    * @author gfrost
+    */
+
+   @UsedByJNICode @Annotations.Experimental public static final int JNI_FLAG_ENABLE_VERBOSE_JNI = 1 << 2;
+
+   /**
+    * Each field (or captured field in the case of an anonymous inner class) referenced by any bytecode rechable from the users Kernel.run(), will 
+    * need to be represented as a <code>KernelArg</code>.
+    *   
+    * @see com.amd.aparapi.Kernel#execute(int _globalSize)
+    * 
+    * @author gfrost
+    *
+    */
+   static class KernelArg{
+
+      /**
+       * The type of this KernelArg.  Created by oring appropriate flags
+       * 
+       * @see ARG_BOOLEAN 
+       * @see ARG_BYTE 
+       * @see ARG_FLOAT 
+       * @see ARG_INT 
+       * @see ARG_DOUBLE 
+       * @see ARG_LONG 
+       * @see ARG_SHORT 
+       * @see ARG_ARRAY 
+       * @see ARG_PRIMITIVE 
+       * @see ARG_READ 
+       * @see ARG_WRITE
+       * @see ARG_LOCAL 
+       * @see ARG_GLOBAL 
+       * @see ARG_CONSTANT 
+       * @see ARG_ARRAYLENGTH 
+       * @see ARG_APARAPI_BUF 
+       * @see ARG_EXPLICIT 
+       * @see ARG_EXPLICIT_WRITE 
+       * @see ARG_OBJ_ARRAY_STRUCT 
+       * @see ARG_APARAPI_BUF_HAS_ARRAY 
+       * @see ARG_APARAPI_BUF_IS_DIRECT  
+       */
+      @UsedByJNICode public int type;
+
+      /**
+       * Name of the field
+       */
+      @UsedByJNICode public String name;
+
+      /**
+       * If this field represents a Java array then the instance will be captured here
+       */
+      @UsedByJNICode public Object javaArray;
+
+      /**
+       * If this is an array or a buffer then the size (in bytes) is held here
+       */
+      @UsedByJNICode public int sizeInBytes;
+
+      /**
+       * If this is an array buffer then the number of elements is stored here
+       */
+      @UsedByJNICode public int numElements;
+
+      /**
+       * If this is an array buffer then the number of elements is stored here.
+       * 
+       * At present only set for AparapiLocalBuffer objs, JNI multiplies this by localSize
+       */
+      @Annotations.Unused @UsedByJNICode public int bytesPerLocalSize;
+
+      /**
+       * Only set for array objs, not used on JNI
+       */
+      @UsedByJNICode public Object array;
+
+      /**
+       *  Field in Kernel class corresponding to this arg 
+       */
+      @UsedByJNICode public Field field;
+
+      /**
+       * The byte array for obj conversion passed to opencl 
+       */
+      byte[] objArrayBuffer;
+
+      /**
+       * The ByteBuffer fronting the byte array 
+
+       */
+
+      ByteBuffer objArrayByteBuffer;
+
+      /**
+       * ClassModel of the array elements (not used on JNI side)
+       * 
+       */
+      ClassModel objArrayElementModel;
+
+      /**
+       * Only set for AparapiBuffer objs,
+       */
+      Object primitiveBuf;
+
+      /**
+       * Size of this primitive
+       */
+      int primitiveSize;
+   }
+
+   private long jniContextHandle = 0;
+
+   private Kernel kernel;
+
+   private Entrypoint entryPoint;
+
+   private int argc;
+
+   /**
+    * Create a KernelRunner for a specific Kernel instance.  
+    * @param _kernel
+    */
+   KernelRunner(Kernel _kernel) {
+      kernel = _kernel;
+
+   }
+
+   /**
+    * <code>Kernel.dispose()</code> delegates to <code>KernelRunner.dispose()</code> which delegates to <code>disposeJNI()</code> to actually close JNI data structures.<br/>
+    * 
+    * @see KernelRunner#disposeJNI()
+    */
+   void dispose() {
+      if (kernel.getExecutionMode().isOpenCL()) {
+         disposeJNI(jniContextHandle);
+      }
+   }
+
+   /**
+    *  TODO:
+    *  
+    *  synchronized to avoid race in clGetPlatformIDs() in OpenCL lib  problem should fixed in some future OpenCL version
+    *  
+    * @param _kernel 
+    * @param _flags
+    * @param numProcessors
+    * @param maxJTPLocalSize
+    * @return
+    */
+   @Annotations.DocMe private native static synchronized long initJNI(Kernel _kernel, int _flags, int numProcessors,
+         int maxJTPLocalSize);
+
+   private native long buildProgramJNI(long _jniContextHandle, String _source);
+
+   private native int setArgsJNI(long _jniContextHandle, KernelArg[] _args, int argc);
+
+   private native int runKernelJNI(long _jniContextHandle, int _globalSize, int _localSize, boolean _needSync,
+         boolean useNullForLocalSize, int _passes);
+
+   private native int disposeJNI(long _jniContextHandle);
+
+   private native int getLocalSizeJNI(long _jniContextHandle, int _globalSize, int localBytesPerLocalId);
+
+   private native String getExtensions(long _jniContextHandle);
+
+   private Set<String> capabilitiesSet;
+
+   private long accumulatedExecutionTime = 0;
+
+   private long conversionTime = 0;
+
+   private long executionTime = 0;
+
+   boolean hasFP64Support() {
+      if (capabilitiesSet == null)
+         throw new IllegalStateException("Capabilities queried before they were initialized");
+      return (capabilitiesSet.contains(CL_KHR_FP64) || capabilitiesSet.contains(CL_AMD_FP64));
+   }
+
+   boolean hasSelectFPRoundingModeSupport() {
+      if (capabilitiesSet == null)
+         throw new IllegalStateException("Capabilities queried before they were initialized");
+
+      return capabilitiesSet.contains(CL_KHR_SELECT_FPROUNDING_MODE);
+   }
+
+   boolean hasGlobalInt32BaseAtomicsSupport() {
+      if (capabilitiesSet == null)
+         throw new IllegalStateException("Capabilities queried before they were initialized");
+      return capabilitiesSet.contains(CL_KHR_GLOBAL_INT32_BASE_ATOMICS);
+   }
+
+   boolean hasGlobalInt32ExtendedAtomicsSupport() {
+      if (capabilitiesSet == null)
+         throw new IllegalStateException("Capabilities queried before they were initialized");
+      return capabilitiesSet.contains(CL_KHR_GLOBAL_INT32_EXTENDED_ATOMICS);
+   }
+
+   boolean hasLocalInt32BaseAtomicsSupport() {
+      if (capabilitiesSet == null)
+         throw new IllegalStateException("Capabilities queried before they were initialized");
+      return capabilitiesSet.contains(CL_KHR_LOCAL_INT32_BASE_ATOMICS);
+   }
+
+   boolean hasLocalInt32ExtendedAtomicsSupport() {
+      if (capabilitiesSet == null)
+         throw new IllegalStateException("Capabilities queried before they were initialized");
+      return capabilitiesSet.contains(CL_KHR_LOCAL_INT32_EXTENDED_ATOMICS);
+   }
+
+   boolean hasInt64BaseAtomicsSupport() {
+      if (capabilitiesSet == null)
+         throw new IllegalStateException("Capabilities queried before they were initialized");
+      return capabilitiesSet.contains(CL_KHR_INT64_BASE_ATOMICS);
+   }
+
+   boolean hasInt64ExtendedAtomicsSupport() {
+      if (capabilitiesSet == null)
+         throw new IllegalStateException("Capabilities queried before they were initialized");
+      return capabilitiesSet.contains(CL_KHR_INT64_EXTENDED_ATOMICS);
+   }
+
+   boolean has3DImageWritesSupport() {
+      if (capabilitiesSet == null)
+         throw new IllegalStateException("Capabilities queried before they were initialized");
+      return capabilitiesSet.contains(CL_KHR_3D_IMAGE_WRITES);
+   }
+
+   boolean hasByteAddressableStoreSupport() {
+      if (capabilitiesSet == null)
+         throw new IllegalStateException("Capabilities queried before they were initialized");
+      return capabilitiesSet.contains(CL_KHR_BYTE_ADDRESSABLE_SUPPORT);
+   }
+
+   boolean hasFP16Support() {
+      if (capabilitiesSet == null)
+         throw new IllegalStateException("Capabilities queried before they were initialized");
+      return capabilitiesSet.contains(CL_KHR_FP16);
+   }
+
+   boolean hasGLSharingSupport() {
+      if (capabilitiesSet == null)
+         throw new IllegalStateException("Capabilities queried before they were initialized");
+      return capabilitiesSet.contains(CL_KHR_GL_SHARING);
+   }
+
+   private static int numCores = Runtime.getRuntime().availableProcessors();
+
+   private static int maxJTPLocalSize = Config.JTPLocalSizeMultiplier * numCores;
+
+   static int getMaxJTPLocalSize() {
+      return maxJTPLocalSize;
+   }
+
+   /**
+    * We need to match OpenCL's algorithm for localsize.
+    * 
+    * @param _globalSize The globalsize requested by the user (via <code>Kernel.execute(globalSize)</code>)
+    * @return The value we use for JTP execution for localSize
+    */
+   private static int getJTPLocalSizeForGlobalSize(int _globalSize) {
+      // iterate down until we find a localSize that divides _globalSize equally
+      for (int localSize = getMaxJTPLocalSize(); localSize > 0; localSize--) {
+         if (_globalSize % localSize == 0) {
+            if (logger.isLoggable(Level.FINE)) {
+               logger.fine("executeJava: picking localSize=" + localSize + " for globalSize=" + _globalSize);
+            }
+            return localSize;
+         }
+      }
+      return 0;
+   }
+
+   /**
+    * Execute using a Java thread pool.  Either because we were explicitly asked to do so, or because we 'fall back' after discovering an OpenCL issue.
+    * @param _globalSize The globalSize requested by the user (via <code>Kernel.execute(globalSize)</code>)
+    * @param _passes The # of passes requested by the user (via <code>Kernel.execute(globalSize, passes)</code>).  Note this is usually defaulted to 1 via  <code>Kernel.execute(globalSize)</code>.
+    * @return
+    */
+   private long executeJava(final int _globalSize, final int _passes) {
+      if (logger.isLoggable(Level.FINE)) {
+         logger.fine("executeJava: _globalSize=" + _globalSize);
+      }
+
+      if (kernel.getExecutionMode().equals(EXECUTION_MODE.SEQ)) {
+
+         kernel.localBarrier = new CyclicBarrier(1);
+
+         kernel.setSizes(_globalSize, 1);
+
+         kernel.setNumGroups(_globalSize);
+         Kernel worker = (Kernel) kernel.clone();
+         for (int passid = 0; passid < _passes; passid++) {
+            worker.setPassId(passid);
+            for (int id = 0; id < _globalSize; id++) {
+               worker.setGroupId(id);
+               worker.setGlobalId(id);
+               worker.setLocalId(0);
+               worker.run();
+            }
+         }
+      } else {
+         // note uses of final so we can use in anonymous inner class
+         final int localSize = getJTPLocalSizeForGlobalSize(_globalSize);
+         // if (localSize == 0) return 0;  // should never happen
+         final int numGroups = _globalSize / localSize;
+
+         // compute numThreadSets by multiplying localSize until bigger than numCores
+         final int numThreadSets = localSize >= numCores ? 1 : (numCores + (localSize - 1)) / localSize;
+         final int numThreads = numThreadSets * localSize;
+         // when dividing to get groupsPerThreadSet, round up 
+         final int groupsPerThreadSet = (numGroups + (numThreadSets - 1)) / numThreadSets;
+         if (logger.isLoggable(Level.FINE)) {
+            logger.fine("executeJava: localSize=" + localSize + ", numThreads=" + numThreads + ", numThreadSets=" + numThreadSets
+                  + ", numGroups=" + numGroups);
+         }
+
+         Thread[] threads = new Thread[numThreads];
+         // joinBarrier that says all threads are finished
+         final CyclicBarrier joinBarrier = new CyclicBarrier(numThreads + 1);
+
+         // each threadSet shares a CyclicBarrier of size localSize
+         final CyclicBarrier localBarriers[] = new CyclicBarrier[numThreadSets];
+         kernel.setSizes(_globalSize, localSize);
+         kernel.setNumGroups(numGroups);
+         for (int passid = 0; passid < _passes; passid++) {
+            kernel.setPassId(passid);
+            for (int thrSetId = 0; thrSetId < numThreadSets; thrSetId++) {
+               final int startGroupId = thrSetId * groupsPerThreadSet;
+               final int endGroupId = Math.min((thrSetId + 1) * groupsPerThreadSet, numGroups);
+               // System.out.println("thrSetId=" + thrSetId + " running groups from " + startGroupId + " thru " + (endGroupId-1));
+               localBarriers[thrSetId] = new CyclicBarrier(localSize);
+
+               // each threadSet has localSize threads
+               for (int lid = 0; lid < localSize; lid++) { // for each thread in threadSet
+                  final int localId = lid;
+                  final int threadId = thrSetId * localSize + localId;
+                  final Kernel worker = (Kernel) kernel.clone();
+                  worker.setLocalId(localId);
+                  worker.localBarrier = localBarriers[thrSetId]; // barrier that the kernel has access to
+
+                  threads[threadId] = new Thread(new Runnable(){
+                     @Override public void run() {
+                        for (int groupId = startGroupId; groupId < endGroupId; groupId++) {
+                           int globalId = (groupId * localSize) + localId;
+                           worker.setGroupId(groupId);
+                           worker.setGlobalId(globalId);
+                           // System.out.println("running worker with gid=" + globalId + ", lid=" + localId 
+                           //				   + ", groupId=" + groupId + ", threadId=" + threadId);
+                           worker.run();
+                        }
+                        try {
+                           joinBarrier.await();
+                        } catch (InterruptedException e) {
+                           // TODO Auto-generated catch block
+                           e.printStackTrace();
+                        } catch (BrokenBarrierException e) {
+                           // TODO Auto-generated catch block
+                           e.printStackTrace();
+                        }
+                     }
+                  });
+                  threads[threadId].start();
+               }
+
+               // this is where the main thread waits on the join barrier
+               try {
+                  joinBarrier.await();
+               } catch (InterruptedException e) {
+                  // TODO Auto-generated catch block
+                  e.printStackTrace();
+               } catch (BrokenBarrierException e) {
+                  // TODO Auto-generated catch block
+                  e.printStackTrace();
+               }
+            }
+         }
+      } // execution mode == JTP
+      return 0;
+   }
+
+   private KernelArg[] args = null;
+
+   private boolean usesOopConversion = false;
+
+   /**
+    * 
+    * @param arg
+    * @return
+    * @throws AparapiException
+    */
+   private boolean prepareOopConversionBuffer(KernelArg arg) throws AparapiException {
+      usesOopConversion = true;
+      Class<?> arrayClass = arg.field.getType();
+      ClassModel c = null;
+      boolean didReallocate = false;
+
+      if (arg.objArrayElementModel == null) {
+         String tmp = arrayClass.getName().substring(2).replace("/", ".");
+         String arrayClassInDotForm = tmp.substring(0, tmp.length() - 1);
+
+         if (logger.isLoggable(Level.FINE)) {
+            logger.fine("looking for type = " + arrayClassInDotForm);
+         }
+
+         // get ClassModel of obj array from entrypt.objectArrayFieldsClasses
+         c = entryPoint.getObjectArrayFieldsClasses().get(arrayClassInDotForm);
+         arg.objArrayElementModel = c;
+      } else {
+         c = arg.objArrayElementModel;
+      }
+      assert c != null : "should find class for elements " + arrayClass.getName();
+
+      int arrayBaseOffset = UnsafeWrapper.arrayBaseOffset(arrayClass);
+      int arrayScale = UnsafeWrapper.arrayIndexScale(arrayClass);
+
+      if (logger.isLoggable(Level.FINEST)) {
+         logger.finest("Syncing obj array type = " + arrayClass + " cvtd= " + c.getClassWeAreModelling().getName()
+               + "arrayBaseOffset=" + arrayBaseOffset + " arrayScale=" + arrayScale);
+      }
+
+      int objArraySize = 0;
+      Object newRef = null;
+      try {
+         newRef = arg.field.get(kernel);
+         objArraySize = Array.getLength(newRef);
+      } catch (IllegalAccessException e) {
+         throw new AparapiException(e);
+      }
+
+      assert newRef != null && objArraySize != 0 : "no data";
+
+      int totalStructSize = c.getTotalStructSize();
+      int totalBufferSize = objArraySize * totalStructSize;
+
+      // allocate ByteBuffer if first time or array changed
+      if (arg.objArrayBuffer == null || newRef != arg.array) {
+         ByteBuffer structBuffer = ByteBuffer.allocate(totalBufferSize);
+         arg.objArrayByteBuffer = structBuffer.order(ByteOrder.LITTLE_ENDIAN);
+         arg.objArrayBuffer = arg.objArrayByteBuffer.array();
+         didReallocate = true;
+         if (logger.isLoggable(Level.FINEST)) {
+            logger.finest("objArraySize = " + objArraySize + " totalStructSize= " + totalStructSize + " totalBufferSize="
+                  + totalBufferSize);
+         }
+      } else {
+         arg.objArrayByteBuffer.clear();
+      }
+
+      // copy the fields that the JNI uses
+      arg.javaArray = arg.objArrayBuffer;
+      arg.numElements = objArraySize;
+      arg.sizeInBytes = totalBufferSize;
+
+      for (int j = 0; j < objArraySize; j++) {
+         int sizeWritten = 0;
+
+         Object object = UnsafeWrapper.getObject(newRef, arrayBaseOffset + arrayScale * j);
+         for (int i = 0; i < c.getStructMemberTypes().size(); i++) {
+            TypeSpec t = c.getStructMemberTypes().get(i);
+            long offset = c.getStructMemberOffsets().get(i);
+
+            if (logger.isLoggable(Level.FINEST)) {
+               logger.finest("name = " + c.getStructMembers().get(i).getNameAndTypeEntry().getNameUTF8Entry().getUTF8() + " t= "
+                     + t);
+            }
+
+            switch (t) {
+               case I: {
+                  int x = UnsafeWrapper.getInt(object, offset);
+                  arg.objArrayByteBuffer.putInt(x);
+                  sizeWritten += t.getSize();
+                  break;
+               }
+               case F: {
+                  float x = UnsafeWrapper.getFloat(object, offset);
+                  arg.objArrayByteBuffer.putFloat(x);
+                  sizeWritten += t.getSize();
+                  break;
+               }
+               case J: {
+                  long x = UnsafeWrapper.getLong(object, offset);
+                  arg.objArrayByteBuffer.putLong(x);
+                  sizeWritten += t.getSize();
+                  break;
+               }
+               case Z: {
+                  boolean x = UnsafeWrapper.getBoolean(object, offset);
+                  arg.objArrayByteBuffer.put(x == true ? (byte) 1 : (byte) 0);
+                  // Booleans converted to 1 byte C chars for opencl
+                  sizeWritten += TypeSpec.B.getSize();
+                  break;
+               }
+               case B: {
+                  byte x = UnsafeWrapper.getByte(object, offset);
+                  arg.objArrayByteBuffer.put(x);
+                  sizeWritten += t.getSize();
+                  break;
+               }
+               case D: {
+                  throw new AparapiException("Double not implemented yet");
+               }
+               default:
+                  assert true == false : "typespec did not match anything";
+                  throw new AparapiException("Unhandled type in buffer conversion");
+            }
+         }
+
+         // add padding here if needed
+         if (logger.isLoggable(Level.FINEST)) {
+            logger.finest("sizeWritten = " + sizeWritten + " totalStructSize= " + totalStructSize);
+         }
+
+         assert sizeWritten <= totalStructSize : "wrote too much into buffer";
+
+         while (sizeWritten < totalStructSize) {
+            if (logger.isLoggable(Level.FINEST)) {
+               logger.finest(arg.name + " struct pad byte = " + sizeWritten + " totalStructSize= " + totalStructSize);
+            }
+            arg.objArrayByteBuffer.put((byte) -1);
+            sizeWritten++;
+         }
+      }
+
+      assert arg.objArrayByteBuffer.arrayOffset() == 0 : "should be zero";
+
+      return didReallocate;
+   }
+
+   private void extractOopConversionBuffer(KernelArg arg) throws AparapiException {
+      Class<?> arrayClass = arg.field.getType();
+      ClassModel c = arg.objArrayElementModel;
+      assert c != null : "should find class for elements: " + arrayClass.getName();
+      assert arg.array != null : "array is null";
+
+      int arrayBaseOffset = UnsafeWrapper.arrayBaseOffset(arrayClass);
+      int arrayScale = UnsafeWrapper.arrayIndexScale(arrayClass);
+      if (logger.isLoggable(Level.FINEST)) {
+         logger.finest("Syncing field:" + arg.name + ", bb=" + arg.objArrayByteBuffer + ", type = " + arrayClass);
+      }
+
+      int objArraySize = 0;
+      try {
+         objArraySize = Array.getLength(arg.field.get(kernel));
+      } catch (IllegalAccessException e) {
+         throw new AparapiException(e);
+      }
+
+      assert objArraySize > 0 : "should be > 0";
+
+      int totalStructSize = c.getTotalStructSize();
+      //int totalBufferSize = objArraySize * totalStructSize;
+      //assert arg.objArrayBuffer.length == totalBufferSize : "size should match";
+
+      arg.objArrayByteBuffer.rewind();
+
+      for (int j = 0; j < objArraySize; j++) {
+         int sizeWritten = 0;
+         Object object = UnsafeWrapper.getObject(arg.array, arrayBaseOffset + arrayScale * j);
+         for (int i = 0; i < c.getStructMemberTypes().size(); i++) {
+            TypeSpec t = c.getStructMemberTypes().get(i);
+            long offset = c.getStructMemberOffsets().get(i);
+            switch (t) {
+               case I: {
+                  // read int value from buffer and store into obj in the array
+                  int x = arg.objArrayByteBuffer.getInt();
+                  if (logger.isLoggable(Level.FINEST)) {
+                     logger.finest("fType = " + t.getShortName() + " x= " + x);
+                  }
+                  UnsafeWrapper.putInt(object, offset, x);
+                  sizeWritten += t.getSize();
+                  break;
+               }
+               case F: {
+                  float x = arg.objArrayByteBuffer.getFloat();
+                  if (logger.isLoggable(Level.FINEST)) {
+                     logger.finest("fType = " + t.getShortName() + " x= " + x);
+                  }
+                  UnsafeWrapper.putFloat(object, offset, x);
+                  sizeWritten += t.getSize();
+                  break;
+               }
+               case J: {
+                  long x = arg.objArrayByteBuffer.getLong();
+                  if (logger.isLoggable(Level.FINEST)) {
+                     logger.finest("fType = " + t.getShortName() + " x= " + x);
+                  }
+                  UnsafeWrapper.putLong(object, offset, x);
+                  sizeWritten += t.getSize();
+                  break;
+               }
+               case Z: {
+                  byte x = arg.objArrayByteBuffer.get();
+                  if (logger.isLoggable(Level.FINEST)) {
+                     logger.finest("fType = " + t.getShortName() + " x= " + x);
+                  }
+                  UnsafeWrapper.putBoolean(object, offset, (x == 1 ? true : false));
+                  // Booleans converted to 1 byte C chars for open cl
+                  sizeWritten += TypeSpec.B.getSize();
+                  break;
+               }
+               case B: {
+                  byte x = arg.objArrayByteBuffer.get();
+                  if (logger.isLoggable(Level.FINEST)) {
+                     logger.finest("fType = " + t.getShortName() + " x= " + x);
+                  }
+                  UnsafeWrapper.putByte(object, offset, x);
+                  sizeWritten += t.getSize();
+                  break;
+               }
+               case D: {
+                  throw new AparapiException("Double not implemented yet");
+               }
+               default:
+                  assert true == false : "typespec did not match anything";
+                  throw new AparapiException("Unhandled type in buffer conversion");
+            }
+         }
+
+         // add padding here if needed
+         if (logger.isLoggable(Level.FINEST)) {
+            logger.finest("sizeWritten = " + sizeWritten + " totalStructSize= " + totalStructSize);
+         }
+
+         assert sizeWritten <= totalStructSize : "wrote too much into buffer";
+
+         while (sizeWritten < totalStructSize) {
+            // skip over pad bytes
+            arg.objArrayByteBuffer.get();
+            sizeWritten++;
+         }
+      }
+   }
+
+   private void restoreObjects() throws AparapiException {
+      for (int i = 0; i < argc; i++) {
+         KernelArg arg = args[i];
+         if ((arg.type & ARG_OBJ_ARRAY_STRUCT) != 0) {
+            extractOopConversionBuffer(arg);
+         }
+      }
+   }
+
+   // this routine now also finds out how many perLocalItem bytes are specified for this kernel
+   private int localBytesPerLocalId = 0;
+
+   private boolean updateKernelArrayRefs() throws AparapiException {
+      boolean needsSync = false;
+      localBytesPerLocalId = 0;
+
+      for (int i = 0; i < argc; i++) {
+         KernelArg arg = args[i];
+         try {
+            if ((arg.type & ARG_ARRAY) != 0) {
+               Object newArrayRef;
+               newArrayRef = arg.field.get(kernel);
+
+               if (newArrayRef == null) {
+                  throw new IllegalStateException("Cannot send null refs to kernel, reverting to java");
+               }
+
+               if ((arg.type & ARG_OBJ_ARRAY_STRUCT) != 0) {
+                  prepareOopConversionBuffer(arg);
+               } else {
+                  // set up JNI fields for normal arrays
+                  arg.javaArray = newArrayRef;
+                  arg.numElements = Array.getLength(newArrayRef);
+                  arg.sizeInBytes = arg.numElements * arg.primitiveSize;
+
+                  if ((args[i].type & ARG_EXPLICIT) != 0 && puts.contains(newArrayRef)) {
+                     args[i].type |= ARG_EXPLICIT_WRITE;
+                     // System.out.println("detected an explicit write " + args[i].name);
+                     puts.remove(newArrayRef);
+                  }
+               }
+               if (newArrayRef != arg.array) {
+                  needsSync = true;
+                  if (logger.isLoggable(Level.FINE)) {
+                     logger.fine("saw newArrayRef for " + arg.name + " = " + newArrayRef + ", newArrayLen = "
+                           + Array.getLength(newArrayRef));
+                  }
+               }
+               arg.array = newArrayRef;
+               assert arg.array != null : "null array ref";
+            }
+         } catch (IllegalArgumentException e) {
+            e.printStackTrace();
+         } catch (IllegalAccessException e) {
+            e.printStackTrace();
+         }
+      }
+      return needsSync;
+   }
+
+   // private int numAvailableProcessors = Runtime.getRuntime().availableProcessors();
+
+   private Kernel executeOpenCL(final String _entrypointName, final int _globalSize, final int _passes) throws AparapiException {
+
+      // Read the array refs after kernel may have changed them
+      // We need to do this as input to computing the localSize
+      assert args != null : "args should not be null";
+      boolean needSync = updateKernelArrayRefs();
+
+      // note: the above will also recompute the value localBytesPerLocalId
+
+      int localSize = getLocalSizeJNI(jniContextHandle, _globalSize, localBytesPerLocalId);
+      if (localSize == 0) {
+         // should fall back to java?
+         logger.warning("getLocalSizeJNI failed, reverting java");
+         kernel.setFallbackExecutionMode();
+         return execute(_entrypointName, _globalSize, _passes);
+      }
+      assert localSize <= _globalSize : "localSize = " + localSize;
+
+      // Call back to kernel for last minute changes
+      kernel.setSizes(_globalSize, localSize);
+
+      if (needSync && logger.isLoggable(Level.FINE)) {
+         logger.fine("Need to resync arrays on " + kernel.getClass().getName());
+      }
+
+      // native side will reallocate array buffers if necessary
+      if (runKernelJNI(jniContextHandle, _globalSize, localSize, needSync, kernel.useNullForLocalSize, _passes) != 0) {
+         //System.out.println("CL exec seems to have failed");
+         logger.warning("### CL exec seems to have failed. Trying to revert to Java ###");
+         kernel.setFallbackExecutionMode();
+         return execute(_entrypointName, _globalSize, _passes);
+      }
+
+      if (usesOopConversion == true) {
+         restoreObjects();
+      }
+
+      if (logger.isLoggable(Level.FINE)) {
+         logger.fine("executeOpenCL completed. _globalSize=" + _globalSize);
+      }
+      return kernel;
+   }
+
+   synchronized Kernel execute(Kernel.Entry entry, final int _globalSize, final int _passes) {
+      System.out.println("execute(Kernel.Entry, size) not implemented");
+      return (kernel);
+   }
+
+   synchronized private Kernel fallBackAndExecute(String _entrypointName, final int _globalSize, final int _passes) {
+
+      kernel.setFallbackExecutionMode();
+      return execute(_entrypointName, _globalSize, _passes);
+   }
+
+   synchronized private Kernel warnFallBackAndExecute(String _entrypointName, final int _globalSize, final int _passes,
+         Exception _exception) {
+      if (logger.isLoggable(Level.WARNING)) {
+         logger.warning("Reverting to Java Thread Pool (JTP) for " + kernel.getClass() + ": " + _exception.getMessage());
+         _exception.printStackTrace();
+      }
+      return fallBackAndExecute(_entrypointName, _globalSize, _passes);
+   }
+
+   synchronized private Kernel warnFallBackAndExecute(String _entrypointName, final int _globalSize, final int _passes,
+         String _excuse) {
+      logger.warning("Reverting to Java Thread Pool (JTP) for " + kernel.getClass() + ": " + _excuse);
+      return fallBackAndExecute(_entrypointName, _globalSize, _passes);
+   }
+
+   synchronized Kernel execute(String _entrypointName, final int _globalSize, final int _passes) {
+
+      long executeStartTime = System.currentTimeMillis();
+      if (_globalSize == 0) {
+         throw new IllegalStateException("global size can't be 0");
+      }
+
+      if (kernel.getExecutionMode().isOpenCL()) {
+         // System.out.println("OpenCL");
+         if (entryPoint == null) {
+            try {
+               ClassModel classModel = new ClassModel(kernel.getClass());
+               entryPoint = classModel.getEntrypoint(_entrypointName, kernel);
+            } catch (Exception exception) {
+
+               return warnFallBackAndExecute(_entrypointName, _globalSize, _passes, exception);
+            }
+            if (entryPoint != null && !entryPoint.shouldFallback()) {
+
+               int jniFlags = 0;
+               jniFlags |= (Config.enableProfiling ? JNI_FLAG_ENABLE_PROFILING : 0);
+
+               jniFlags |= (Config.enableVerboseJNI ? JNI_FLAG_ENABLE_VERBOSE_JNI : 0);
+               jniFlags |= (kernel.getExecutionMode().equals(EXECUTION_MODE.GPU) ? JNI_FLAG_USE_GPU : 0);
+               // Init the device to check capabilities before emitting the 
+               // code that requires the capabilities.
+               jniContextHandle = initJNI(kernel, jniFlags, Runtime.getRuntime().availableProcessors(), getMaxJTPLocalSize());
+               if (jniContextHandle == 0) {
+                  return warnFallBackAndExecute(_entrypointName, _globalSize, _passes, "initJNI failed to return a valid handle");
+               }
+
+               String extensions = getExtensions(jniContextHandle);
+               capabilitiesSet = new HashSet<String>();
+               StringTokenizer strTok = new StringTokenizer(extensions);
+               while (strTok.hasMoreTokens()) {
+                  capabilitiesSet.add(strTok.nextToken());
+               }
+               if (logger.isLoggable(Level.FINE)) {
+                  logger.fine("Capabilities initialized to :" + capabilitiesSet.toString());
+               }
+
+               if (entryPoint.requiresDoublePragma() && !hasFP64Support()) {
+
+                  return warnFallBackAndExecute(_entrypointName, _globalSize, _passes, "FP64 required but not supported");
+               }
+
+               if (entryPoint.requiresByteAddressableStorePragma() && !hasByteAddressableStoreSupport()) {
+
+                  return warnFallBackAndExecute(_entrypointName, _globalSize, _passes,
+                        "Byte addressable stores required but not supported");
+               }
+
+               boolean all32AtomicsAvailable = hasGlobalInt32BaseAtomicsSupport() && hasGlobalInt32ExtendedAtomicsSupport()
+                     && hasLocalInt32BaseAtomicsSupport() && hasLocalInt32ExtendedAtomicsSupport();
+
+               if (entryPoint.requiresAtomic32Pragma() && !all32AtomicsAvailable) {
+
+                  return warnFallBackAndExecute(_entrypointName, _globalSize, _passes, "32 bit Atomics required but not supported");
+               }
+
+               final StringBuilder openCLStringBuilder = new StringBuilder();
+               KernelWriter openCLWriter = new KernelWriter(){
+                  @Override public void write(String _string) {
+                     openCLStringBuilder.append(_string);
+                  }
+               };
+
+               // Emit the OpenCL source into a string
+               try {
+                  openCLWriter.write(entryPoint);
+
+               } catch (CodeGenException codeGenException) {
+                  return warnFallBackAndExecute(_entrypointName, _globalSize, _passes, codeGenException);
+               }
+               String openCL = openCLStringBuilder.toString();
+               if (Config.enableShowGeneratedOpenCL) {
+                  System.out.println(openCL);
+               }
+               if (logger.isLoggable(Level.INFO)) {
+                  logger.info(openCL);
+               }
+
+               // Send the string to OpenCL to compile it
+               if (buildProgramJNI(jniContextHandle, openCLStringBuilder.toString()) == 0) {
+
+                  return warnFallBackAndExecute(_entrypointName, _globalSize, _passes, "OpenCL compile failed");
+               }
+
+               args = new KernelArg[entryPoint.getReferencedFields().size()];
+               int i = 0;
+
+               for (Field field : entryPoint.getReferencedFields()) {
+                  try {
+                     field.setAccessible(true);
+                     args[i] = new KernelArg();
+                     args[i].name = field.getName();
+                     args[i].field = field;
+
+                     Class<?> type = field.getType();
+                     if (type.isArray()) {
+                        args[i].array = null; // will get updated in updateKernelArrayRefs
+                        args[i].type |= ARG_ARRAY;
+                        if (isExplicit()) {
+                           args[i].type |= ARG_EXPLICIT;
+                        }
+                        // for now, treat all write arrays as read-write, see bugzilla issue 4859
+                        // we might come up with a better solution later
+                        args[i].type |= entryPoint.getArrayFieldAssignments().contains(field.getName()) ? (ARG_WRITE | ARG_READ)
+                              : 0;
+                        args[i].type |= entryPoint.getArrayFieldAccesses().contains(field.getName()) ? ARG_READ : 0;
+                        args[i].type |= ARG_GLOBAL;
+                        args[i].type |= type.isAssignableFrom(float[].class) ? ARG_FLOAT : 0;
+
+                        args[i].type |= type.isAssignableFrom(int[].class) ? ARG_INT : 0;
+
+                        args[i].type |= type.isAssignableFrom(boolean[].class) ? ARG_BOOLEAN : 0;
+
+                        args[i].type |= type.isAssignableFrom(byte[].class) ? ARG_BYTE : 0;
+
+                        args[i].type |= type.isAssignableFrom(double[].class) ? ARG_DOUBLE : 0;
+
+                        args[i].type |= type.isAssignableFrom(long[].class) ? ARG_LONG : 0;
+
+                        args[i].type |= type.isAssignableFrom(short[].class) ? ARG_SHORT : 0;
+
+                        // arrays whose length is used will have an int arg holding
+                        // the length as a kernel param
+                        if (entryPoint.getArrayFieldArrayLengthUsed().contains(args[i].name)) {
+                           args[i].type |= ARG_ARRAYLENGTH;
+                        }
+                        if (type.getName().startsWith("[L")) {
+                           args[i].type |= (ARG_OBJ_ARRAY_STRUCT | ARG_WRITE | ARG_READ);
+                           if (logger.isLoggable(Level.FINE)) {
+                              logger.fine("tagging " + args[i].name + " as (ARG_OBJ_ARRAY_STRUCT | ARG_WRITE | ARG_READ)");
+                           }
+                        }
+
+                     } else if (type.isAssignableFrom(float.class)) {
+                        args[i].type |= ARG_PRIMITIVE;
+                        args[i].type |= ARG_FLOAT;
+                     } else if (type.isAssignableFrom(int.class)) {
+                        args[i].type |= ARG_PRIMITIVE;
+                        args[i].type |= ARG_INT;
+                     } else if (type.isAssignableFrom(double.class)) {
+                        args[i].type |= ARG_PRIMITIVE;
+                        args[i].type |= ARG_DOUBLE;
+                     } else if (type.isAssignableFrom(long.class)) {
+                        args[i].type |= ARG_PRIMITIVE;
+                        args[i].type |= ARG_LONG;
+                     } else if (type.isAssignableFrom(boolean.class)) {
+                        args[i].type |= ARG_PRIMITIVE;
+                        args[i].type |= ARG_BOOLEAN;
+                     } else if (type.isAssignableFrom(byte.class)) {
+                        args[i].type |= ARG_PRIMITIVE;
+                        args[i].type |= ARG_BYTE;
+                     } else if (type.isAssignableFrom(short.class)) {
+                        args[i].type |= ARG_PRIMITIVE;
+                        args[i].type |= ARG_SHORT;
+                     }
+                     // System.out.printf("in execute, arg %d %s %08x\n", i,args[i].name,args[i].type );
+                  } catch (IllegalArgumentException e) {
+                     e.printStackTrace();
+                  }
+                  args[i].primitiveSize = ((args[i].type & ARG_FLOAT) != 0 ? 4 : (args[i].type & ARG_INT) != 0 ? 4
+                        : (args[i].type & ARG_BYTE) != 0 ? 1 : (args[i].type & ARG_BOOLEAN) != 0 ? 1
+                              : (args[i].type & ARG_SHORT) != 0 ? 2 : (args[i].type & ARG_LONG) != 0 ? 8
+                                    : (args[i].type & ARG_DOUBLE) != 0 ? 8 : 0);
+
+                  if (logger.isLoggable(Level.FINE)) {
+                     logger.fine("arg " + i + ", " + args[i].name + ", type=" + Integer.toHexString(args[i].type)
+                           + ", primitiveSize=" + args[i].primitiveSize);
+                  }
+
+                  i++;
+               }
+
+               // at this point, i = the actual used number of arguments
+               // (private buffers do not get treated as arguments)
+
+               argc = i;
+
+               setArgsJNI(jniContextHandle, args, argc);
+
+               conversionTime = System.currentTimeMillis() - executeStartTime;
+
+               try {
+                  executeOpenCL(_entrypointName, _globalSize, _passes);
+               } catch (AparapiException e) {
+                  warnFallBackAndExecute(_entrypointName, _globalSize, _passes, e);
+               }
+            } else {
+               warnFallBackAndExecute(_entrypointName, _globalSize, _passes, "failed to locate entrypoint");
+            }
+
+         } else {
+
+            try {
+               executeOpenCL(_entrypointName, _globalSize, _passes);
+            } catch (AparapiException e) {
+
+               warnFallBackAndExecute(_entrypointName, _globalSize, _passes, e);
+            }
+         }
+
+      } else {
+         executeJava(_globalSize, _passes);
+      }
+      if (Config.enableExecutionModeReporting) {
+         System.out.println(kernel.getClass().getCanonicalName() + ":" + kernel.getExecutionMode());
+      }
+      executionTime = System.currentTimeMillis() - executeStartTime;
+      accumulatedExecutionTime += executionTime;
+
+      return (kernel);
+   }
+
+   private Set<Object> puts = new HashSet<Object>();
+
+   private native int getJNI(long _jniContextHandle, Object _array);
+
+   /**
+    * Enqueue a request to return this array from the GPU. This method blocks until the array is available. 
+    * <br/>
+    * Note that <code>Kernel.put(type [])</code> calls will delegate to this call. 
+    * <br/>
+    * Package protected
+    *  
+    * @param array It is assumed that this parameter is indeed an array (of in, float, short etc). 
+    * 
+    * @see Kernel#get(int[] arr)
+    * @see Kernel#get(short[] arr)
+    * @see Kernel#get(float[] arr)
+    * @see Kernel#get(double[] arr)
+    * @see Kernel#get(long[] arr)
+    */
+   protected void get(Object array) {
+      if (explicit
+            && (kernel.getExecutionMode() == Kernel.EXECUTION_MODE.GPU || kernel.getExecutionMode() == Kernel.EXECUTION_MODE.CPU)) {
+         // Only makes sense when we are using OpenCL
+         getJNI(jniContextHandle, array);
+      }
+   }
+
+   /**
+    * Tag this array so that it is explicitly enqueued before the kernel is executed.
+    * <br/>
+    * Note that <code>Kernel.put(type [])</code> calls will delegate to this call. 
+    * <br/>
+    * Package protected
+    * @param array It is assumed that this parameter is indeed an array (of in, float, short etc). 
+    * @see Kernel#put(int[] arr)
+    * @see Kernel#put(short[] arr)
+    * @see Kernel#put(float[] arr)
+    * @see Kernel#put(double[] arr)
+    * @see Kernel#put(long[] arr)
+    */
+
+   protected void put(Object array) {
+      if (explicit
+            && (kernel.getExecutionMode() == Kernel.EXECUTION_MODE.GPU || kernel.getExecutionMode() == Kernel.EXECUTION_MODE.CPU)) {
+         // Only makes sense when we are using OpenCL
+         puts.add(array);
+      }
+   }
+
+   private boolean explicit = false;
+
+   protected void setExplicit(boolean _explicit) {
+      explicit = _explicit;
+   }
+
+   protected boolean isExplicit() {
+      return (explicit);
+   }
+
+   /**
+    * Determine the time taken to convert bytecode to OpenCL for first Kernel.execute(range) call.
+    * @return The time spent preparing the kernel for execution using GPU
+    * 
+    */
+   public long getConversionTime() {
+      return conversionTime;
+   }
+
+   /**
+    * Determine the execution time of the previous Kernel.execute(range) call.
+    * @return The time spent executing the kernel (ms)
+    * 
+    */
+   public long getExecutionTime() {
+      return executionTime;
+   }
+
+   /**
+    * Determine the accumulated execution time of all previous Kernel.execute(range) calls.
+    * @return The accumulated time spent executing this kernel (ms)
+    * 
+    */
+   public long getAccumulatedExecutionTime() {
+      return accumulatedExecutionTime;
+   }
+
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/KernelWriter.java b/com.amd.aparapi/src/java/com/amd/aparapi/KernelWriter.java
new file mode 100644
index 00000000..a3fc293f
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/KernelWriter.java
@@ -0,0 +1,566 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import com.amd.aparapi.ClassModel.ClassModelField;
+import com.amd.aparapi.ClassModel.AttributePool.LocalVariableTableEntry;
+import com.amd.aparapi.ClassModel.AttributePool.RuntimeAnnotationsEntry;
+import com.amd.aparapi.ClassModel.AttributePool.LocalVariableTableEntry.LocalVariableInfo;
+import com.amd.aparapi.ClassModel.ConstantPool.FieldEntry;
+import com.amd.aparapi.ClassModel.ConstantPool.MethodEntry;
+import com.amd.aparapi.InstructionSet.AccessArrayElement;
+import com.amd.aparapi.InstructionSet.AssignToArrayElement;
+import com.amd.aparapi.InstructionSet.AssignToField;
+import com.amd.aparapi.InstructionSet.AssignToLocalVariable;
+import com.amd.aparapi.InstructionSet.BinaryOperator;
+import com.amd.aparapi.InstructionSet.I_ALOAD_0;
+import com.amd.aparapi.InstructionSet.I_GETFIELD;
+import com.amd.aparapi.InstructionSet.I_INVOKESPECIAL;
+import com.amd.aparapi.InstructionSet.I_IUSHR;
+import com.amd.aparapi.InstructionSet.I_LUSHR;
+import com.amd.aparapi.InstructionSet.MethodCall;
+import com.amd.aparapi.InstructionSet.VirtualMethodCall;
+
+abstract class KernelWriter extends BlockWriter{
+
+   final String cvtBooleanToChar = "char ";
+
+   final String cvtBooleanArrayToCharStar = "char* ";
+
+   final String cvtByteToChar = "char ";
+
+   final String cvtByteArrayToCharStar = "char* ";
+
+   final String cvtIntArrayToIntStar = "int* ";
+
+   final String cvtFloatArrayToFloatStar = "float* ";
+
+   final String cvtDoubleArrayToDoubleStar = "double* ";
+
+   final String cvtLongArrayToLongStar = "long* ";
+
+   final String cvtShortArrayToShortStar = "short* ";
+
+   // private static Logger logger = Logger.getLogger(Config.getLoggerName());
+
+   Entrypoint entryPoint = null;
+
+   final static Map<String, String> javaToCLIdentifierMap = new HashMap<String, String>();
+   {
+      javaToCLIdentifierMap.put("getGlobalId()I", "get_global_id(0)");
+      javaToCLIdentifierMap.put("getGlobalSize()I", "get_global_size(0)");
+      javaToCLIdentifierMap.put("getLocalId()I", "get_local_id(0)");
+      javaToCLIdentifierMap.put("getLocalSize()I", "get_local_size(0)");
+      javaToCLIdentifierMap.put("getNumGroups()I", "get_num_groups(0)");
+      javaToCLIdentifierMap.put("getGroupId()I", "get_group_id(0)");
+      javaToCLIdentifierMap.put("getPassId()I", "get_pass_id(this)");
+      javaToCLIdentifierMap.put("localBarrier()V", "barrier(CLK_LOCAL_MEM_FENCE)");
+      javaToCLIdentifierMap.put("globalBarrier()V", "barrier(CLK_GLOBAL_MEM_FENCE)");
+
+   }
+
+   /**
+    * These three convert functions are here to perform
+    * any type conversion that may be required between 
+    * Java and OpenCL.
+    * @param _typeDesc String in the Java JNI notation, [I, etc 
+    * @return          Suitably converted string, "char*", etc
+    */
+   @Override protected String convertType(String _typeDesc, boolean useClassModel) {
+      if (_typeDesc.equals("Z") || _typeDesc.equals("boolean")) {
+         return (cvtBooleanToChar);
+      } else if (_typeDesc.equals("[Z") || _typeDesc.equals("boolean[]")) {
+         return (cvtBooleanArrayToCharStar);
+      } else if (_typeDesc.equals("B") || _typeDesc.equals("byte")) {
+         return (cvtByteToChar);
+      } else if (_typeDesc.equals("[B") || _typeDesc.equals("byte[]")) {
+         return (cvtByteArrayToCharStar);
+      } else if (_typeDesc.equals("[I") || _typeDesc.equals("int[]")) {
+         return (cvtIntArrayToIntStar);
+      } else if (_typeDesc.equals("[F") || _typeDesc.equals("float[]")) {
+         return (cvtFloatArrayToFloatStar);
+      } else if (_typeDesc.equals("[D") || _typeDesc.equals("double[]")) {
+         return (cvtDoubleArrayToDoubleStar);
+      } else if (_typeDesc.equals("[J") || _typeDesc.equals("long[]")) {
+         return (cvtLongArrayToLongStar);
+      } else if (_typeDesc.equals("[S") || _typeDesc.equals("short[]")) {
+         return (cvtShortArrayToShortStar);
+      }
+      // if we get this far, we haven't matched anything yet
+      if (useClassModel) {
+         return (ClassModel.convert(_typeDesc, "", true));
+      } else {
+         return _typeDesc;
+      }
+   }
+
+   @Override protected void writeMethod(MethodCall _methodCall, MethodEntry _methodEntry) throws CodeGenException {
+
+      // System.out.println("_methodEntry = " + _methodEntry);
+      // special case for buffers
+
+      int argc = _methodEntry.getStackConsumeCount();
+
+      String methodName = _methodEntry.getNameAndTypeEntry().getNameUTF8Entry().getUTF8();
+      String methodSignature = _methodEntry.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8();
+
+      String barrierAndGetterMappings = javaToCLIdentifierMap.get(methodName + methodSignature);
+
+      if (barrierAndGetterMappings != null) {
+         //this is one of the OpenCL barrier or size getter methods
+         //write the mapping and exit
+         write(barrierAndGetterMappings);
+      } else {
+
+         String intrinsicMapping = Kernel.getMappedMethodName(_methodEntry);
+         // System.out.println("getMappedMethodName for " + methodName + " returned " + mapping);
+         boolean isIntrinsic = false;
+
+         if (intrinsicMapping == null) {
+            assert entryPoint != null : "entryPoint should not be null";
+            boolean isSpecial = _methodCall instanceof I_INVOKESPECIAL;
+            MethodModel m = entryPoint.getCallTarget(_methodEntry, isSpecial);
+
+            if (m != null) {
+               write(m.getName());
+            } else {
+               // Must be a library call like rsqrt
+               write(methodName);
+               isIntrinsic = true;
+            }
+         } else {
+            write(intrinsicMapping);
+         }
+
+         write("(");
+
+         if (intrinsicMapping == null && _methodCall instanceof VirtualMethodCall && (!isIntrinsic)) {
+
+            Instruction i = ((VirtualMethodCall) _methodCall).getInstanceReference();
+
+            if (i instanceof I_ALOAD_0) {
+               write("this");
+            } else if (i instanceof AccessArrayElement) {
+               AccessArrayElement arrayAccess = (AccessArrayElement) ((VirtualMethodCall) _methodCall).getInstanceReference();
+               Instruction refAccess = arrayAccess.getArrayRef();
+               assert refAccess instanceof I_GETFIELD : "ref should come from getfield";
+               String fieldName = ((I_GETFIELD) refAccess).getConstantPoolFieldEntry().getNameAndTypeEntry().getNameUTF8Entry()
+                     .getUTF8();
+               write(" &(this->" + fieldName);
+               write("[");
+               writeInstruction(arrayAccess.getArrayIndex());
+               write("])");
+            } else {
+               assert false : "unhandled call from: " + i;
+            }
+         }
+         for (int arg = 0; arg < argc; arg++) {
+            if (intrinsicMapping == null && _methodCall instanceof VirtualMethodCall && (!isIntrinsic) || arg != 0) {
+               write(", ");
+            }
+            writeInstruction(_methodCall.getArg(arg));
+         }
+         write(")");
+      }
+   }
+
+   void writePragma(String _name, boolean _enable) {
+      write("#pragma OPENCL EXTENSION " + _name + " : " + (_enable ? "en" : "dis") + "able");
+      newLine();
+   }
+
+   @Override void write(Entrypoint _entryPoint) throws CodeGenException {
+      List<String> thisStruct = new ArrayList<String>();
+      List<String> argLines = new ArrayList<String>();
+      List<String> assigns = new ArrayList<String>();
+
+      // hack 
+      // for (java.lang.reflect.Field f:_entryPoint.getTheClass().getDeclaredFields()){
+
+      entryPoint = _entryPoint;
+
+      for (ClassModelField field : _entryPoint.getReferencedClassModelFields()) {
+         //Field field = _entryPoint.getClassModel().getField(f.getName());
+         StringBuilder thisStructLine = new StringBuilder();
+         StringBuilder argLine = new StringBuilder();
+         StringBuilder assignLine = new StringBuilder();
+
+         String signature = field.getDescriptor();
+
+         boolean isPointer = false;
+         RuntimeAnnotationsEntry visibleAnnotations = field.fieldAttributePool.getRuntimeVisibleAnnotationsEntry();
+
+         String type = "__global";
+         if (visibleAnnotations != null) {
+            //for (AnnotationInfo ai : visibleAnnotations) {
+            //   String typeDescriptor = ai.getTypeDescriptor();
+            //}
+         }
+
+         if (signature.startsWith("[")) {
+            argLine.append(type + " ");
+            thisStructLine.append(type + " ");
+            isPointer = true;
+            signature = signature.substring(1);
+         }
+
+         // If it is a converted array of objects, emit the struct param
+         String className = null;
+         if (signature.startsWith("L")) {
+            // Turn Lcom/amd/javalabs/opencl/demo/DummyOOA; into com_amd_javalabs_opencl_demo_DummyOOA for example
+            className = (signature.substring(1, signature.length() - 1)).replace("/", "_");
+            //if (logger.isLoggable(Level.FINE)) {
+            //   logger.fine("Examining object parameter: " + signature + " new: " + className);
+            //}
+
+            argLine.append(className);
+            thisStructLine.append(className);
+         } else {
+            argLine.append(convertType(ClassModel.typeName(signature.charAt(0)), false));
+            thisStructLine.append(convertType(ClassModel.typeName(signature.charAt(0)), false));
+         }
+
+         argLine.append(" ");
+         thisStructLine.append(" ");
+
+         if (isPointer) {
+            argLine.append("*");
+            thisStructLine.append("*");
+         }
+         assignLine.append("this->");
+         assignLine.append(field.getName());
+         assignLine.append(" = ");
+         assignLine.append(field.getName());
+         argLine.append(field.getName());
+         thisStructLine.append(field.getName());
+         assigns.add(assignLine.toString());
+         argLines.add(argLine.toString());
+         thisStruct.add(thisStructLine.toString());
+
+         // Add int field into "this" struct for supporting java arraylength op
+         // named like foo__javaArrayLength
+         if (isPointer && _entryPoint.getArrayFieldArrayLengthUsed().contains(field.getName())) {
+            StringBuilder lenStructLine = new StringBuilder();
+            StringBuilder lenArgLine = new StringBuilder();
+            StringBuilder lenAssignLine = new StringBuilder();
+
+            lenStructLine.append("int " + field.getName() + BlockWriter.arrayLengthMangleSuffix);
+
+            lenAssignLine.append("this->");
+            lenAssignLine.append(field.getName() + BlockWriter.arrayLengthMangleSuffix);
+            lenAssignLine.append(" = ");
+            lenAssignLine.append(field.getName() + BlockWriter.arrayLengthMangleSuffix);
+
+            lenArgLine.append("int " + field.getName() + BlockWriter.arrayLengthMangleSuffix);
+
+            assigns.add(lenAssignLine.toString());
+            argLines.add(lenArgLine.toString());
+            thisStruct.add(lenStructLine.toString());
+         }
+      }
+
+      if (Config.enableByteWrites || _entryPoint.requiresByteAddressableStorePragma()) {
+         // Starting with OpenCL 1.1 (which is as far back as we support)
+         // this feature is part of the core, so we no longer need this pragma
+         if (false) {
+            writePragma("cl_khr_byte_addressable_store", true);
+            newLine();
+         }
+      }
+
+      boolean usesAtomics = false;
+      if (Config.enableAtomic32 || _entryPoint.requiresAtomic32Pragma()) {
+         usesAtomics = true;
+         writePragma("cl_khr_global_int32_base_atomics", true);
+         writePragma("cl_khr_global_int32_extended_atomics", true);
+         writePragma("cl_khr_local_int32_base_atomics", true);
+         writePragma("cl_khr_local_int32_extended_atomics", true);
+      }
+      if (Config.enableAtomic64 || _entryPoint.requiresAtomic64Pragma()) {
+         usesAtomics = true;
+         writePragma("cl_khr_int64_base_atomics", true);
+         writePragma("cl_khr_int64_extended_atomics", true);
+      }
+      if (usesAtomics) {
+         write("int atomicAdd(__global int *_arr, int _index, int _delta){");
+         in();
+         {
+            newLine();
+            write("return atomic_add(&_arr[_index], _delta);");
+            out();
+            newLine();
+         }
+         write("}");
+
+         newLine();
+      }
+
+      if (Config.enableDoubles || _entryPoint.requiresDoublePragma()) {
+         writePragma("cl_amd_fp64", true);
+         newLine();
+      }
+
+      // Emit structs for oop transformation accessors
+      for (ClassModel cm : _entryPoint.getObjectArrayFieldsClasses().values()) {
+         ArrayList<FieldEntry> fieldSet = cm.getStructMembers();
+         if (fieldSet.size() > 0) {
+            String mangledClassName = cm.getClassWeAreModelling().getName().replace(".", "_");
+            newLine();
+            write("typedef struct " + mangledClassName + "_s{");
+            in();
+            newLine();
+
+            int totalSize = 0;
+            int alignTo = 0;
+
+            Iterator<FieldEntry> it = fieldSet.iterator();
+            while (it.hasNext()) {
+               FieldEntry field = it.next();
+               String fType = field.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8();
+               int fSize = InstructionSet.TypeSpec.valueOf(fType.equals("Z") ? "B" : fType).getSize();
+
+               if (fSize > alignTo) {
+                  alignTo = fSize;
+               }
+               totalSize += fSize;
+
+               String cType = convertType(field.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8(), true);
+               assert cType != null : "could not find type for " + field.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8();
+               writeln(cType + " " + field.getNameAndTypeEntry().getNameUTF8Entry().getUTF8() + ";");
+            }
+
+            // compute total size for OpenCL buffer
+            int totalStructSize = 0;
+            if (totalSize % alignTo == 0) {
+               totalStructSize = totalSize;
+            } else {
+               // Pad up if necessary
+               totalStructSize = ((totalSize / alignTo) + 1) * alignTo;
+            }
+            if (totalStructSize > alignTo) {
+               while (totalSize < totalStructSize) {
+                  //structBuffer.put((byte)-1);
+                  writeln("char _pad_" + totalSize + ";");
+                  totalSize++;
+               }
+            }
+
+            out();
+            newLine();
+            write("} " + mangledClassName + ";");
+            newLine();
+         }
+      }
+
+      write("typedef struct This_s{");
+
+      in();
+      newLine();
+      for (String line : thisStruct) {
+         write(line);
+         writeln(";");
+      }
+      write("int passid");
+      out();
+      writeln(";");
+      // out();
+      //  newLine();
+      write("}This;");
+      newLine();
+      write("int get_pass_id(This *this){");
+      in();
+      {
+         newLine();
+         write("return this->passid;");
+         out();
+         newLine();
+      }
+      write("}");
+      newLine();
+
+      for (MethodModel mm : _entryPoint.getCalledMethods()) {
+         // write declaration :)
+
+         String returnType = mm.getReturnType();
+         // Arrays always map to __global arrays
+         if (returnType.startsWith("[")) {
+            write(" __global ");
+         }
+         write(convertType(returnType, true));
+
+         write(mm.getName());
+
+         if (mm.getMethod().getClassModel() == _entryPoint.getClassModel()
+               || mm.getMethod().getClassModel().isSuperClass(_entryPoint.getClassModel().getClassWeAreModelling())) {
+            write("(This *this");
+         } else {
+            // Call to an object member or superclass of member
+            for (ClassModel c : _entryPoint.getObjectArrayFieldsClasses().values()) {
+               if (mm.getMethod().getClassModel() == c) {
+                  write("( __global " + mm.getMethod().getClassModel().getClassWeAreModelling().getName().replace(".", "_")
+                        + " *this");
+                  break;
+               } else if (mm.getMethod().getClassModel().isSuperClass(c.getClassWeAreModelling())) {
+                  write("( __global " + c.getClassWeAreModelling().getName().replace(".", "_") + " *this");
+                  break;
+               }
+            }
+         }
+         LocalVariableTableEntry lvte = mm.getLocalVariableTableEntry();
+         for (LocalVariableInfo lvi : lvte) {
+            if (lvi.getStart() == 0 && lvi.getVariableIndex() != 0) { // full scope but skip this
+               String descriptor = lvi.getVariableDescriptor();
+               write(", ");
+
+               // Arrays always map to __global arrays
+               if (descriptor.startsWith("[")) {
+                  write(" __global ");
+               }
+
+               write(convertType(descriptor, true));
+               write(lvi.getVariableName());
+            }
+         }
+         write(")");
+         writeMethodBody(mm);
+         newLine();
+      }
+
+      write("__kernel void " + _entryPoint.getMethodModel().getSimpleName() + "(");
+
+      in();
+      boolean first = true;
+      for (String line : argLines) {
+
+         if (first) {
+            first = false;
+         } else {
+            write(", ");
+         }
+
+         newLine();
+         write(line);
+      }
+
+      if (first) {
+         first = false;
+      } else {
+         write(", ");
+      }
+      newLine();
+      write("int passid");
+      out();
+      newLine();
+      write("){");
+      in();
+      newLine();
+      writeln("This thisStruct;");
+      writeln("This* this=&thisStruct;");
+      for (String line : assigns) {
+         write(line);
+         writeln(";");
+      }
+      write("this->passid = passid");
+      writeln(";");
+
+      writeMethodBody(_entryPoint.getMethodModel());
+      out();
+      newLine();
+      writeln("}");
+      out();
+
+   }
+
+   @Override protected void writeThisRef() {
+
+      write("this->");
+
+   }
+
+   @Override void writeInstruction(Instruction _instruction) throws CodeGenException {
+      if (_instruction instanceof I_IUSHR || _instruction instanceof I_LUSHR) {
+         BinaryOperator binaryInstruction = (BinaryOperator) _instruction;
+         Instruction parent = binaryInstruction.getParentExpr();
+         boolean needsParenthesis = true;
+
+         if (parent instanceof AssignToLocalVariable) {
+            needsParenthesis = false;
+         } else if (parent instanceof AssignToField) {
+            needsParenthesis = false;
+         } else if (parent instanceof AssignToArrayElement) {
+            needsParenthesis = false;
+         }
+         if (needsParenthesis) {
+            write("(");
+         }
+
+         if (binaryInstruction instanceof I_IUSHR) {
+            write("((unsigned int)");
+         } else {
+            write("((unsigned long)");
+         }
+         writeInstruction(binaryInstruction.getLhs());
+         write(")");
+         write(" >> ");
+         writeInstruction(binaryInstruction.getRhs());
+
+         if (needsParenthesis) {
+            write(")");
+         }
+      } else {
+         super.writeInstruction(_instruction);
+      }
+   }
+
+   static String writeToString(Entrypoint _entrypoint) throws CodeGenException {
+      final StringBuilder openCLStringBuilder = new StringBuilder();
+      KernelWriter openCLWriter = new KernelWriter(){
+         @Override void write(String _string) {
+            openCLStringBuilder.append(_string);
+         }
+      };
+      openCLWriter.write(_entrypoint);
+      return (openCLStringBuilder.toString());
+   }
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/MethodModel.java b/com.amd.aparapi/src/java/com/amd/aparapi/MethodModel.java
new file mode 100644
index 00000000..bf400ef2
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/MethodModel.java
@@ -0,0 +1,1588 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.amd.aparapi.ClassModel.ClassModelMethod;
+import com.amd.aparapi.ClassModel.ConstantPool;
+import com.amd.aparapi.ClassModel.AttributePool.LocalVariableTableEntry;
+import com.amd.aparapi.ClassModel.AttributePool.LocalVariableTableEntry.LocalVariableInfo;
+import com.amd.aparapi.ClassModel.ConstantPool.FieldEntry;
+import com.amd.aparapi.ClassModel.ConstantPool.MethodReferenceEntry;
+import com.amd.aparapi.ClassModel.ConstantPool.MethodReferenceEntry.Arg;
+import com.amd.aparapi.InstructionPattern.InstructionMatch;
+import com.amd.aparapi.InstructionSet.AccessArrayElement;
+import com.amd.aparapi.InstructionSet.AccessField;
+import com.amd.aparapi.InstructionSet.AccessInstanceField;
+import com.amd.aparapi.InstructionSet.AccessLocalVariable;
+import com.amd.aparapi.InstructionSet.AssignToArrayElement;
+import com.amd.aparapi.InstructionSet.AssignToInstanceField;
+import com.amd.aparapi.InstructionSet.AssignToLocalVariable;
+import com.amd.aparapi.InstructionSet.Branch;
+import com.amd.aparapi.InstructionSet.CastOperator;
+import com.amd.aparapi.InstructionSet.CloneInstruction;
+import com.amd.aparapi.InstructionSet.DUP;
+import com.amd.aparapi.InstructionSet.FieldArrayElementAssign;
+import com.amd.aparapi.InstructionSet.FieldArrayElementIncrement;
+import com.amd.aparapi.InstructionSet.I_AASTORE;
+import com.amd.aparapi.InstructionSet.I_ARETURN;
+import com.amd.aparapi.InstructionSet.I_ATHROW;
+import com.amd.aparapi.InstructionSet.I_BASTORE;
+import com.amd.aparapi.InstructionSet.I_CALOAD;
+import com.amd.aparapi.InstructionSet.I_CASTORE;
+import com.amd.aparapi.InstructionSet.I_DUP;
+import com.amd.aparapi.InstructionSet.I_DUP2;
+import com.amd.aparapi.InstructionSet.I_DUP_X1;
+import com.amd.aparapi.InstructionSet.I_DUP_X2;
+import com.amd.aparapi.InstructionSet.I_GETFIELD;
+import com.amd.aparapi.InstructionSet.I_GETSTATIC;
+import com.amd.aparapi.InstructionSet.I_IADD;
+import com.amd.aparapi.InstructionSet.I_ICONST_1;
+import com.amd.aparapi.InstructionSet.I_IINC;
+import com.amd.aparapi.InstructionSet.I_INVOKEINTERFACE;
+import com.amd.aparapi.InstructionSet.I_INVOKESTATIC;
+import com.amd.aparapi.InstructionSet.I_LOOKUPSWITCH;
+import com.amd.aparapi.InstructionSet.I_MONITORENTER;
+import com.amd.aparapi.InstructionSet.I_MONITOREXIT;
+import com.amd.aparapi.InstructionSet.I_PUTFIELD;
+import com.amd.aparapi.InstructionSet.I_PUTSTATIC;
+import com.amd.aparapi.InstructionSet.I_TABLESWITCH;
+import com.amd.aparapi.InstructionSet.IncrementInstruction;
+import com.amd.aparapi.InstructionSet.InlineAssignInstruction;
+import com.amd.aparapi.InstructionSet.MethodCall;
+import com.amd.aparapi.InstructionSet.MultiAssignInstruction;
+import com.amd.aparapi.InstructionSet.New;
+import com.amd.aparapi.InstructionSet.Return;
+
+class MethodModel{
+   static Logger logger = Logger.getLogger(Config.getLoggerName());
+
+   private ExpressionList expressionList;
+
+   private ClassModelMethod method;
+
+   /**
+      True is an indication to use the fp64 pragma
+   */
+   private boolean usesDoubles;
+
+   /**
+      True is an indication to use the byte addressable store pragma
+   */
+   private boolean usesByteWrites;
+
+   private boolean methodIsGetter;
+
+   private boolean methodIsSetter;
+
+   // Only setters can use putfield
+   private boolean usesPutfield;
+
+   private FieldEntry accessorVariableFieldEntry;
+
+   boolean isGetter() {
+      return methodIsGetter;
+   }
+
+   boolean isSetter() {
+      return methodIsSetter;
+   }
+
+   boolean methodUsesPutfield() {
+      return usesPutfield;
+   }
+
+   ClassModelMethod getMethod() {
+      return method;
+   }
+
+   FieldEntry getAccessorVariableFieldEntry() {
+      return accessorVariableFieldEntry;
+   }
+
+   private Set<MethodModel> calledMethods = new HashSet<MethodModel>();
+
+   Set<MethodModel> getCalledMethods() {
+      return calledMethods;
+   }
+
+   void checkForRecursion(Set<MethodModel> transitiveCalledMethods) throws AparapiException {
+
+      if (transitiveCalledMethods.contains(this)) {
+         throw new ClassParseException(ClassParseException.TYPE.RECURSION, getName());
+      }
+
+      // Add myself
+      transitiveCalledMethods.add(this);
+
+      // For each callee, send him a copy of the call chain up to this method
+      Iterator<MethodModel> cmi = getCalledMethods().iterator();
+      while (cmi.hasNext()) {
+         MethodModel next = cmi.next();
+         next.checkForRecursion(transitiveCalledMethods);
+      }
+
+      // Done examining this call path, remove myself
+      transitiveCalledMethods.remove(this);
+   }
+
+   /**
+    * After we have folded the top level instructions this root list will contain a list of all of the 'root' instructions (stores/loops/conditionals) 
+    * We are going to build a linked list.  Here we track the head and tail
+    */
+   private Instruction pcTail = null;
+
+   private Instruction pcHead = null;
+
+   /**
+    * Look at each instruction for use of long/double or byte writes which
+    * require pragmas to be used in the OpenCL source
+    * 
+    */
+   void setRequiredPragmas(Instruction instruction) {
+      boolean setDouble = instruction.getByteCode().usesDouble();
+      if (setDouble) {
+         usesDoubles = true;
+         if (logger.isLoggable(Level.FINE)) {
+            logger.fine("Found D on =" + instruction + " in " + getName());
+         }
+      }
+      if (instruction instanceof I_BASTORE || instruction instanceof I_CASTORE /* || instruction instanceof I_SASTORE */) {
+         usesByteWrites = true;
+         if (usesByteWrites && logger.isLoggable(Level.FINE)) {
+            logger.fine("Found Byte Addressable Store on =" + instruction + " in " + getName());
+         }
+      }
+   }
+
+   boolean requiresDoublePragma() {
+      return usesDoubles;
+   }
+
+   boolean requiresByteAddressableStorePragma() {
+      return usesByteWrites;
+   }
+
+   /**
+    * Create a linked list of instructions (from pcHead to pcTail).
+    * 
+    * Returns a map of int (pc) to Instruction which to allow us to quickly get from a bytecode offset to the appropriate instruction. 
+    * 
+    * Note that not all int values from 0 to code.length values will map to a valid instruction, if pcMap.get(n) == null then this implies
+    * that 'n' is not the start of an instruction
+    * 
+    * So either pcMap.get(i)== null or pcMap.get(i).getThisPC()==i
+    * 
+    * @return Map<Integer, Instruction> the returned pc to Instruction map
+    */
+   Map<Integer, Instruction> createListOfInstructions() throws ClassParseException {
+      Map<Integer, Instruction> pcMap = new HashMap<Integer, Instruction>();
+      byte[] code = method.getCode();
+
+      // We create a byteReader for reading the bytes from the code array
+      ByteReader codeReader = new ByteReader(code);
+      while (codeReader.hasMore()) {
+         // Create an instruction from code reader's current position
+         int pc = codeReader.getOffset();
+         Instruction instruction = InstructionSet.ByteCode.create(this, codeReader);
+
+         if ((!Config.enablePUTFIELD) && instruction instanceof I_PUTFIELD) {
+            // Special case putfield handling to allow object setter processing
+            // and bail later if necessary
+            //throw new ClassParseException("We don't support putfield instructions");
+            usesPutfield = true;
+         }
+
+         if ((!Config.enableARETURN) && instruction instanceof I_ARETURN) {
+            throw new ClassParseException(instruction, ClassParseException.TYPE.ARRAY_RETURN);
+         }
+
+         if ((!Config.enablePUTSTATIC) && instruction instanceof I_PUTSTATIC) {
+            throw new ClassParseException(instruction, ClassParseException.TYPE.PUTFIELD);
+         }
+         if ((!Config.enableINVOKESTATIC) && instruction instanceof I_INVOKESTATIC) {
+            throw new ClassParseException(instruction, ClassParseException.TYPE.INVOKESTATIC);
+         }
+         if ((!Config.enableINVOKEINTERFACE) && instruction instanceof I_INVOKEINTERFACE) {
+            throw new ClassParseException(instruction, ClassParseException.TYPE.INVOKEINTERFACE);
+         }
+         if ((!Config.enableGETSTATIC) && instruction instanceof I_GETSTATIC) {
+            throw new ClassParseException(instruction, ClassParseException.TYPE.GETSTATIC);
+         }
+         if ((!Config.enableATHROW) && instruction instanceof I_ATHROW) {
+            throw new ClassParseException(instruction, ClassParseException.TYPE.ATHROW);
+         }
+         if ((!Config.enableMONITOR) && ((instruction instanceof I_MONITORENTER) || (instruction instanceof I_MONITOREXIT))) {
+            throw new ClassParseException(instruction, ClassParseException.TYPE.SYNCHRONIZE);
+         }
+         if ((!Config.enableNEW) && instruction instanceof New) {
+            throw new ClassParseException(instruction, ClassParseException.TYPE.NEW);
+         }
+         if (instruction instanceof I_CALOAD || instruction instanceof I_CASTORE) {
+            throw new ClassParseException(instruction, ClassParseException.TYPE.CHARARRAY);
+         }
+         if (instruction instanceof I_AASTORE) {
+            throw new ClassParseException(instruction, ClassParseException.TYPE.ARRAYALIAS);
+         }
+
+         if (instruction instanceof I_GETFIELD) {
+            I_GETFIELD getFieldInstr = (I_GETFIELD) instruction;
+            if (getFieldInstr.getConstantPoolFieldEntry().getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8().endsWith("C")) {
+               throw new ClassParseException(instruction, ClassParseException.TYPE.ACCESSTOCHARFIELD);
+            }
+         }
+
+         if ((!Config.enableSWITCH) && (instruction instanceof I_LOOKUPSWITCH || instruction instanceof I_TABLESWITCH)) {
+            throw new ClassParseException(instruction, ClassParseException.TYPE.SWITCH);
+         }
+         if (!Config.enableMETHODARRAYPASSING) {
+            if (instruction instanceof MethodCall) {
+               MethodCall methodCall = (MethodCall) instruction;
+
+               MethodReferenceEntry methodReferenceEntry = methodCall.getConstantPoolMethodEntry();
+               if (!Kernel.isMappedMethod(methodReferenceEntry)) { // we will allow trusted methods to violate this rule
+                  for (Arg arg : methodReferenceEntry.getArgs()) {
+                     if (arg.isArray()) {
+                        throw new ClassParseException(instruction, ClassParseException.TYPE.METHODARRAYARG);
+
+                     }
+                  }
+               }
+            }
+         }
+
+         setRequiredPragmas(instruction);
+
+         pcMap.put(pc, instruction);
+
+         // list maintenance, make this the pcHead if pcHead is null
+         if (pcHead == null) {
+            pcHead = instruction;
+         }
+
+         // extend the list of instructions here we make the new instruction point to previous tail
+         instruction.setPrevPC(pcTail);
+         // if tail exists (not the first instruction in the list) link it to the new instruction
+         if (pcTail != null) {
+            pcTail.setNextPC(instruction);
+         }
+         // now move the tail along
+         pcTail = instruction;
+
+      }
+      return (pcMap);
+   }
+
+   /**
+    * Here we connect the branch nodes to the instruction that they branch to.
+    * <p>
+    * Each branch node contains a 'target' field indended to reference the node that the branch targets. Each instruction also contain four seperate lists of branch nodes that reference it.
+    * These lists hold forwardConditional, forwardUnconditional, reverseConditional and revereseUnconditional branches that reference it.
+    * <p>
+    * So assuming that we had a branch node at pc offset 100 which represented 'goto 200'. 
+    * <p>
+    * Following this call the branch node at pc offset 100 will have a 'target' field which actually references the instruction at pc offset 200, and the instruction at pc offset 200 will 
+    * have the branch node (at 100) added to it's forwardUnconditional list.
+    * 
+    * @see InstructionSet.Branch#getTarget()
+    * @see Instruction#getForwardConditionalTargets()
+    * @see Instruction#getForwardUnconditionalTargets()
+    * @see Instruction#getReverseConditionalTargets()
+    * @see Instruction#getReverseUnconditionalTargets()
+    */
+   void buildBranchGraphs(Map<Integer, Instruction> pcMap) {
+
+      for (Instruction instruction = pcHead; instruction != null; instruction = instruction.getNextPC()) {
+         if (instruction.isBranch()) {
+            Branch branch = instruction.asBranch();
+            Instruction targetInstruction = pcMap.get(branch.getAbsolute());
+            branch.setTarget(targetInstruction);
+         }
+      }
+
+   }
+
+   /**
+    * Javac optimizes some branches to avoid goto->goto, branch->goto etc.  
+    * 
+    * This method specifically deals with reverse branches which are the result of such optimisations. 
+    * 
+    * <code><pre>
+    * 
+    * </pre></code>
+    * 
+    * 
+    * 
+    */
+   void deoptimizeReverseBranches() {
+
+      for (Instruction instruction = pcHead; instruction != null; instruction = instruction.getNextPC()) {
+         if (instruction.isBranch()) {
+            Branch branch = instruction.asBranch();
+            if (branch.isReverse()) {
+               Instruction target = branch.getTarget();
+               LinkedList<Branch> list = target.getReverseUnconditionalBranches();
+               if (list != null && list.size() > 0 && list.get(list.size() - 1) != branch) {
+                  Branch unconditional = list.get(list.size() - 1).asBranch();
+                  branch.retarget(unconditional);
+
+               }
+            }
+         }
+      }
+   }
+
+   /**
+    * DUP family of instructions break our stack unwind model (whereby we treat instructions like the oeprands they create/consume).
+    * 
+    * <p>
+    * Here we replace DUP style instructions with a 'mock' instruction which 'clones' the effect of the instruction.  This would be invalid to execute but is useful 
+    * to replace the DUP with a 'pattern' which it simulates.  This allows us to later apply transforms to represent the original code. 
+    * 
+    * <p>
+    * An example might be the bytecode for the following sequence.
+    * <code><pre>
+    *    results[10]++; 
+         return
+    * </pre></code>
+    * 
+    * Which results in the following bytecode
+    * <code><pre>
+      0:   aload_0       // reference through 'this' to get 
+      1:   getfield      // field 'results' which is an array of int
+      4:   bipush  10    // push the array index
+      6:   dup2          // dreaded dup2 we'll come back here
+      7:   iaload        // ignore for the moment.
+      8:   iconst_1
+      9:   iadd
+      10:  iastore
+      11:  return
+    * </pre></code>
+    * 
+    * First we need to know what the stack will look like before the dup2 is encountered.
+    * Using our folding technique we represent the first two instructions inside ()
+    * 
+    * <pre><code>
+           getfield (aload_0     // result in the array field reference on stack
+           bipush  10            // the array index
+           dup2                  // dreaded dup2 we'll come back here
+    * </code></pre>
+    * 
+    * The <code>dup2</code> essentially copies the top two elements on the stack.  So we emulate this by replacing the dup2 with clones of the instructions which would reinstate the same stack state. 
+    * <p>
+    * So after the <code>dup2</code> transform we end up with:- 
+    * <pre><code>
+          getfield (aload_0)     // result in the array field reference on stack
+          bipush  10             // the array index
+          {getfield (aload_0)}   // result in the array field reference on stack
+          {bipush 10}            // the array index
+    * </code></pre>
+    * 
+    * So carrying on lets look at the <code>iaload</code> which consumes two operands (the index and the array field reference) and creates one (the result of an array access)
+    * 
+    * <pre><code>
+          getfield (aload_0)     // result in the array field reference on stack
+          bipush  10             // the array index
+          {getfield (aload_0)}   // result in the array field reference on stack
+          {bipush  10}           // the array index
+          iaload 
+    * </code></pre>
+    *
+    * So we now have 
+    * 
+    * <pre><code>
+          getfield (aload_0)                        // result in the array field reference on stack
+          bipush  10                                // the array index
+          iaload ({getfield(aload_0), {bipush 10})  // results in the array element on the stack
+          iconst
+          iadd
+    * </code></pre>
+    * 
+    * And if you are following along the <code>iadd</code> will fold the previous two stack entries essentially pushing the result of  
+    * <code>results[10]+1<code> on the stack.
+    *   
+    * <pre><code>
+          getfield (aload_0)                                        // result in the array field reference on stack
+          bipush  10                                                // the array index
+          iadd (iaload ({getfield(aload_0), {bipush 10}, iconst_1)  // push of results[10]+1 
+    * </code></pre>
+    * Then the final <code>istore</code> instruction which consumes 3 stack operands (the field array reference, the index and the value to assign).
+    * 
+    * <p>
+    * Which results in 
+    * <pre><code> 
+          istore (getfield (aload_0), bipush 10,  iadd (iaload ({getfield(aload_0), {bipush 10}, iconst_1)) // results[10] = results[10+1]
+    * </code></pre> 
+    * 
+    * Where <code>results[10] = results[10+1]<code> is the long-hand form of the <code>results[10]++</code>
+    * and will be transformed by one of the 'inc' transforms to the more familiar form a little later. 
+    * 
+    * @param _expressionList
+    * @param _instruction
+    * @throws ClassParseException
+    */
+   void txFormDups(ExpressionList _expressionList, final Instruction _instruction) throws ClassParseException {
+      if (_instruction instanceof I_DUP) {
+         Instruction e = _expressionList.getTail();
+         while (!e.producesStack()) {
+            e = e.getPrevExpr();
+         }
+         _expressionList.add(new CloneInstruction(this, e));
+         System.out.println("clone of " + e);
+      } else if (_instruction instanceof I_DUP2) {
+
+         Instruction e = _expressionList.getTail();
+         while (!e.producesStack()) {
+            e = e.getPrevPC();
+         }
+         Instruction clone = e;
+         e = e.getPrevExpr();
+         while (!e.producesStack()) {
+            e = e.getPrevExpr();
+         }
+         _expressionList.add(new CloneInstruction(this, e));
+         _expressionList.add(new CloneInstruction(this, clone));
+      } else if (_instruction instanceof I_DUP_X1) {
+
+         Instruction e = _expressionList.getTail();
+
+         while (!e.producesStack()) {
+            e = e.getPrevExpr();
+         }
+         Instruction clone1 = new CloneInstruction(this, e);
+         e = e.getPrevExpr();
+         while (!e.producesStack()) {
+            e = e.getPrevExpr();
+         }
+         _expressionList.insertBetween(e.getPrevExpr(), e, clone1);
+
+      } else if (_instruction instanceof I_DUP_X2) {
+
+         // dup_x2 duplicates top operand and jams a copy in 3 down from the top
+         // ...word3, word2, word1 => ...word1, word3, word2, word1
+
+         Instruction e = _expressionList.getTail();
+
+         if (logger.isLoggable(Level.FINE)) {
+            logger.fine("Found DUP_X2 prev=" + e.getPrevExpr() + " e=" + e + " curr=" + _instruction);
+         }
+
+         // Get the previous instr to write to stack "word1" 
+         while (!e.producesStack()) {
+            if (logger.isLoggable(Level.FINE)) {
+               logger.fine("DUP_X2 skipping to find write: e=" + e);
+            }
+            e = e.getPrevExpr();
+         }
+
+         // Clone it, this will replace the dup action
+         Instruction clone1 = new CloneInstruction(this, e);
+
+         if (logger.isLoggable(Level.FINE)) {
+            logger.fine("DUP_X2 cloning: clone1=" + clone1);
+         }
+
+         // Skip over 2 earlier writes to stack and capture 3rd one 
+         e = e.getPrevExpr();
+
+         for (int i = 0; i < 2;) {
+            if (logger.isLoggable(Level.FINE)) {
+               logger.fine("DUP_X2 skipping to find insert: e=" + e);
+            }
+            if (e.producesStack()) {
+               i++;
+            }
+            if (i < 2) {
+               e = e.getPrevExpr();
+            }
+         }
+
+         if (logger.isLoggable(Level.FINE)) {
+            logger.fine("DUP_X2 insert: prev=" + e.getPrevExpr() + " e=" + e + " clone=" + clone1);
+         }
+
+         // Add our clone in between those two writes
+         _expressionList.insertBetween(e.getPrevExpr(), e, clone1);
+
+      } else if (_instruction instanceof DUP) {
+
+         throw new ClassParseException(_instruction, ClassParseException.TYPE.UNSUPPORTEDBYTECODE);
+      }
+
+   }
+
+   /**
+    *  Try to fold the instructions into higher level structures. 
+    * At the end we have a folded instruction tree with 'roots' containing the 
+    * top level branches (stores mostly)
+    * @throws ClassParseException
+    */
+
+   void foldExpressions() throws ClassParseException {
+
+      // we also populate a second list of expressions held between headTail.head and headTail.tail
+
+      for (Instruction instruction = pcHead; instruction != null; instruction = instruction.getNextPC()) {
+
+         // Here we are going to extract loop/if/structure from the list that we have collected so far in the roots list 
+         // We are looking for a new instruction which is the target of a forward branch (this is why we collected forward branch counts) we only enter this loop
+         // however if roots list is not empty and it's tail is not a forward branch. 
+
+         expressionList.foldComposite(instruction);
+
+         // If we find a DUP then we need to txform the DUP into a set of clones on the xpressionlist
+         if (instruction instanceof DUP) {
+            txFormDups(expressionList, instruction);
+         } else {
+            if (instruction.consumesStack()) {
+               // If instruction consumes n operands, then walk back until we find n roots on the xpressionlist that produce stack. 
+               // we will user this cursor to track our progress
+               Instruction cursor = expressionList.getTail();
+
+               // set this flag if we pass something that does not produce stack
+               boolean foundNonStackProducer = false;
+
+               // operandStart will points to the beginning of the list of consumed operands
+               Instruction operandStart = null;
+
+               // back up from root tail past each instruction expecting to create a consumed operand for this instruction
+               for (int i = 0; i < instruction.getStackConsumeCount();) {
+                  if (!cursor.producesStack()) {
+                     foundNonStackProducer = true; // we spotted an instruction that does not consume stack. So we need to analyze this
+                  } else {
+                     i++;
+                  }
+                  operandStart = cursor;
+                  cursor = cursor.getPrevExpr();
+               }
+
+               // if we found something that did not consume stack we probably have an expression with a side effect 
+
+               if (foundNonStackProducer) {
+                  // Something like
+                  //     a = b++;
+                  //     foo(i++);
+                  //     return(a++);
+                  // so we need to check for common transformations
+                  applyTransformations(expressionList, instruction, operandStart);
+               }
+
+               // cut the tail off and give it to instruction
+               Instruction childTail = expressionList.getTail();
+               Instruction childHead = expressionList.createList(cursor);
+
+               instruction.setChildren(childHead, childTail);
+            }
+            // add this instruction to the tail of roots
+            expressionList.add(instruction);
+         }
+      }
+   }
+
+   InstructionTransformer[] transformers = new InstructionTransformer[] {
+
+         new InstructionTransformer("long hand post increment of field"){
+
+            /**
+             * 
+             * <pre><code>
+             *                 A                                     A
+             *                 |                                     |
+             *         +1, 0  getfield<f>                            |
+             *                 |              / getfield<f>         Increment(fieldref<f>++)
+             *          0, 0  putfield<f> - iadd                     |
+             *                 |              \ i_const_1            |
+             *                 B                                     B
+             *                 
+             *                 A                                     A
+             *                 |                                     |
+             *         +1, 0  getfield<f>                            |
+             *                 |                      / getfield<f>  Increment(fieldRef<f>++)
+             *          0, 0  putfield<f> - i2<t> iadd               |
+             *                 |                      \ i_const_1    |
+             *                 B                                     B
+             * </code></pre>
+             */
+
+            @Override public Instruction transform(final ExpressionList _expressionList, final Instruction i) {
+               InstructionMatch result = null;
+
+               if (Config.enablePUTFIELD
+                     && (result = InstructionPattern.accessInstanceField.matches(i, InstructionPattern.assignToInstanceField)).ok) {
+
+                  Instruction accessRaw = i;
+                  Instruction assignRaw = i.getNextExpr();
+                  AccessInstanceField access = (AccessInstanceField) i.getReal();
+                  AssignToInstanceField assign = (AssignToInstanceField) i.getNextExpr().getReal();
+                  if (access.getConstantPoolFieldIndex() == assign.getConstantPoolFieldIndex()) {
+                     Instruction child = ((Instruction) assign).getFirstChild().getNextExpr();
+
+                     if (child instanceof CastOperator) {
+                        child = child.getFirstChild();
+                     }
+                     if (child instanceof I_IADD) {
+                        I_IADD add = (I_IADD) child;
+                        Instruction lhs = add.getLhs();
+                        Instruction rhs = add.getRhs();
+                        if (lhs instanceof AccessInstanceField) {
+                           if (rhs instanceof I_ICONST_1) {
+                              IncrementInstruction inc = new IncrementInstruction(MethodModel.this, (Instruction) access, true,
+                                    false);
+                              _expressionList.replaceInclusive((Instruction) accessRaw, (Instruction) assignRaw, inc);
+                              return (inc);
+                           }
+                        }
+                     }
+                  }
+               }
+               return (null);
+            }
+         },
+         new InstructionTransformer("long hand pre increment of field"){
+            /**
+             * <pre>
+             *                 A                                     A
+             *                 |                                     |
+             *                 |  / getfield<f>                      |
+             *         +1, -2 iadd                                   |
+             *                 |  \ i_const_1                       Increment(++fieldref<f>)
+             *                 |                / getfield<f>        |
+             *         +0, -1 putfield<f> -- iadd                    |
+             *                 |                \ i_const_1          |
+             *                 B                                     B
+             * </pre>
+             */
+
+            @Override public Instruction transform(final ExpressionList _expressionList, final Instruction i) {
+               InstructionMatch result = null;
+               if (Config.enablePUTFIELD
+                     && (result = InstructionPattern.fieldPlusOne.matches(i, InstructionPattern.assignToInstanceField)).ok) {
+
+                  Instruction topAddRaw = i;
+                  Instruction assignRaw = i.getNextExpr();
+                  I_IADD topAdd = (I_IADD) i.getReal();
+                  AssignToInstanceField assign = (AssignToInstanceField) i.getNextExpr().getReal();
+                  Instruction topLhs = topAdd.getLhs().getReal();
+                  Instruction topRhs = topAdd.getRhs().getReal();
+                  if (topLhs instanceof AccessInstanceField) {
+                     AccessInstanceField topLhsAccess = (AccessInstanceField) topLhs;
+                     if (topRhs instanceof I_ICONST_1) {
+                        if (topLhsAccess.getConstantPoolFieldIndex() == assign.getConstantPoolFieldIndex()) {
+                           Instruction child = ((Instruction) assign).getFirstChild().getNextExpr();
+                           Instruction valueToAssign = assign.getValueToAssign();
+                           if (valueToAssign instanceof I_IADD) {
+
+                              I_IADD add = (I_IADD) child;
+                              Instruction lhs = add.getLhs();
+                              Instruction rhs = add.getRhs();
+                              if (lhs instanceof AccessInstanceField) {
+                                 if (rhs instanceof I_ICONST_1) {
+
+                                    IncrementInstruction inc = new IncrementInstruction(MethodModel.this,
+                                          (Instruction) topLhsAccess, true, true);
+                                    _expressionList.replaceInclusive((Instruction) topAddRaw, (Instruction) assignRaw, inc);
+
+                                    return (inc);
+                                 }
+                              }
+                           }
+                        }
+
+                     }
+                  }
+
+               }
+               return (null);
+            }
+         },
+         new InstructionTransformer("long hand post increment of local variable"){
+            /**
+             * <pre>
+             *                 A                                     A
+             *                 |                                     |
+             *         +1, 0  iload&ltn&gt                               |
+             *                 |              / iload&ltn&gt            Increment(varref&ltn&gt++)
+             *          0, 0  istore&ltn&gt - iadd                       |
+             *                 |              \ i_const_1            |
+             *                 B                                     B
+             *                 
+             *                 A                                     A
+             *                 |                                     |
+             *         +1, 0  &ltt&gtload&ltn&gt                             |
+             *                 |                      / iload&ltn&gt    Increment( varref&ltn&gt++)
+             *          0, 0  &ltt&gtstore&ltn&gt - i2&ltt&gt iadd               |
+             *                 |                      \ i_const_1    |
+             *                 B                                     B
+             * </pre>
+             */
+            @Override public Instruction transform(ExpressionList _expressionList, Instruction i) {
+               // looking for a post increment on a local variable
+               InstructionMatch result = null;
+               if ((result = InstructionPattern.accessLocalVariable.matches(i, InstructionPattern.longHandIncLocalVariable)).ok) {
+
+                  AccessLocalVariable access = (AccessLocalVariable) i;
+                  AssignToLocalVariable assign = (AssignToLocalVariable) i.getNextExpr();
+                  if (access.getLocalVariableTableIndex() == assign.getLocalVariableTableIndex()) {
+                     IncrementInstruction inc = new IncrementInstruction(MethodModel.this, (Instruction) access, true, false);
+                     _expressionList.replaceInclusive((Instruction) access, (Instruction) assign, inc);
+                     return (inc);
+                  }
+               }
+               return (null);
+            }
+
+         },
+         new InstructionTransformer("long hand post decrement of local variable"){
+            /**
+             * <pre>
+             *                 A                                     A
+             *                 |                                     |
+             *         +1, 0  iload<n>                               |
+             *                 |              / iload<n>            Decrement(varref<n>--)
+             *          0, 0  istore<n> - isub                       |
+             *                 |              \ i_const_1            |
+             *                 B                                     B
+             *                 
+             *                 A                                     A
+             *                 |                                     |
+             *         +1, 0  <t>load<n>                             |
+             *                 |                      / iload<n>    Decrement( varref<n>--)
+             *          0, 0  <t>store<n> - i2<t> isub               |
+             *                 |                      \ i_const_1    |
+             *                 B                                     B
+             * </pre>
+             */
+            @Override public Instruction transform(ExpressionList _expressionList, Instruction i) {
+
+               InstructionMatch result = null;
+               if ((result = InstructionPattern.accessLocalVariable.matches(i, InstructionPattern.longHandDecLocalVariable)).ok) {
+
+                  AccessLocalVariable access = (AccessLocalVariable) i;
+                  AssignToLocalVariable assign = (AssignToLocalVariable) i.getNextExpr();
+                  if (access.getLocalVariableTableIndex() == assign.getLocalVariableTableIndex()) {
+                     IncrementInstruction inc = new IncrementInstruction(MethodModel.this, (Instruction) access, false, false);
+                     _expressionList.replaceInclusive((Instruction) access, (Instruction) assign, inc);
+                     return (inc);
+                  }
+               }
+               return (null);
+            }
+
+         },
+         new InstructionTransformer("long hand pre increment of local variable"){
+            /**
+             * <pre>
+             *                 A                                     A
+             *                 |              / iload<n>             |
+             *          0, 0  istore<n> - iadd                       |
+             *                 |              \ i_const_1            Increment(++varref<n>)
+             *         +1, 0  iload<n>                               |
+             *                 |                                     |           
+             *                 B                                     B
+             *                 
+             *                 A                                     A
+             *                 |                      / iload<n>     |
+             *          0, 0  <t>store<n> - i2<t> iadd               |
+             *                 |                      \ i_const_1    Increment( ++varref<n>)
+             *         +1, 0  <t>load<n>                             |
+             *                 |                                     |
+             *                 B                                     B
+             * </pre>
+             */
+            @Override public Instruction transform(ExpressionList _expressionList, Instruction i) {
+
+               InstructionMatch result = null;
+               // pre increment local variable
+               if ((result = InstructionPattern.longHandIncLocalVariable.matches(i, InstructionPattern.accessLocalVariable)).ok) {
+
+                  AssignToLocalVariable assign = (AssignToLocalVariable) i;
+                  AccessLocalVariable access = (AccessLocalVariable) i.getNextExpr();
+                  if (access.getLocalVariableTableIndex() == assign.getLocalVariableTableIndex()) {
+                     IncrementInstruction inc = new IncrementInstruction(MethodModel.this, (Instruction) access, true, true);
+                     _expressionList.replaceInclusive((Instruction) assign, (Instruction) access, inc);
+                     return (inc);
+                  }
+
+               }
+
+               return (null);
+            }
+
+         },
+         new InstructionTransformer("inline assign - say for methiod call or logical expression - "){
+            /**
+             * <pre>
+             *                 A                                     A
+             *                 |                                     |
+             *          0, 0  iload<n>                               |
+             *                 |       / iload<n>               InlineAssign(istore<?>, iload<n>)
+             *         +1, 0  istore<?>                              |
+             *                 |                                     |           
+             *                 B                                     B
+             * </pre>
+             */
+            @Override public Instruction transform(ExpressionList _expressionList, Instruction i) {
+
+               InstructionMatch result = null;
+
+               if ((result = InstructionPattern.accessLocalVariable.matches(i, InstructionPattern.assignToLocalVariable)).ok) {
+
+                  AccessLocalVariable access = (AccessLocalVariable) i;
+                  if (access.getLocalVariableTableIndex() != 0) { // we don;t want to trap on 'this' references ;) 
+                     AssignToLocalVariable assign = (AssignToLocalVariable) i.getNextExpr();
+                     if (access.getLocalVariableTableIndex() != assign.getLocalVariableTableIndex()) {
+                        InlineAssignInstruction inlineAssign = new InlineAssignInstruction(MethodModel.this, assign,
+                              (Instruction) access);
+                        _expressionList.replaceInclusive((Instruction) access, (Instruction) assign, inlineAssign);
+                        return (inlineAssign);
+                     }
+                  }
+               }
+
+               return (null);
+            }
+
+         },
+         new InstructionTransformer("pre increment of local variable"){
+
+            @Override public Instruction transform(ExpressionList _expressionList, Instruction i) {
+
+               InstructionMatch result = null;
+               if ((result = InstructionPattern.inc.matches(i, InstructionPattern.accessLocalVariable)).ok) {
+
+                  I_IINC iinc = (I_IINC) i;
+                  AccessLocalVariable access = (AccessLocalVariable) i.getNextExpr();
+                  if (iinc.getLocalVariableTableIndex() == access.getLocalVariableTableIndex()) {
+
+                     IncrementInstruction inc = new IncrementInstruction(MethodModel.this, (Instruction) access, iinc.isInc(), true);
+                     _expressionList.replaceInclusive(iinc, (Instruction) access, inc);
+                     return (inc);
+                  }
+               }
+               return (null);
+            }
+
+         },
+         new InstructionTransformer("post increment of local variable"){
+
+            @Override public Instruction transform(ExpressionList _expressionList, Instruction i) {
+
+               InstructionMatch result = null;
+
+               if ((result = InstructionPattern.accessLocalVariable.matches(i, InstructionPattern.inc)).ok) {
+
+                  AccessLocalVariable access = (AccessLocalVariable) i;
+                  I_IINC iinc = (I_IINC) i.getNextExpr();
+
+                  if (iinc.getLocalVariableTableIndex() == access.getLocalVariableTableIndex()) {
+
+                     IncrementInstruction inc = new IncrementInstruction(MethodModel.this, (Instruction) access, iinc.isInc(),
+                           false);
+                     _expressionList.replaceInclusive((Instruction) access, iinc, inc);
+                     return (inc);
+                  }
+               }
+               return (null);
+            }
+
+         },
+         new InstructionTransformer("inline assign of local variable (with cast)"){
+            /**
+             * <pre>
+             *                 A                                     A
+             *                 |      /exp                           |
+             *          0, 0  cast<n>                                |
+             *                 |       / iload<n>               InlineAssign(istore<?>, cast)
+             *         +1, 0  istore<?>                              |
+             *                 |                                     |           
+             *                 B                                     B
+             * </pre>
+             */
+            @Override public Instruction transform(ExpressionList _expressionList, Instruction i) {
+
+               InstructionMatch result = null;
+               if ((result = InstructionPattern.cast.matches(i, InstructionPattern.assignToLocalVariable)).ok) {
+
+                  CastOperator cast = (CastOperator) i;
+
+                  AssignToLocalVariable assign = (AssignToLocalVariable) i.getNextExpr();
+
+                  InlineAssignInstruction inlineAssign = new InlineAssignInstruction(MethodModel.this, assign, (Instruction) cast);
+                  _expressionList.replaceInclusive((Instruction) cast, (Instruction) assign, inlineAssign);
+                  return (inlineAssign);
+
+               }
+               return (null);
+            }
+
+         },
+         new InstructionTransformer("field array element pre increment with nested index (local variable) pre increment"){
+            /**
+             * <pre>
+             *                 A                                     A
+             *                 |            / getfield - aload       |
+             *                 |    / iaload                         |
+             *                 |   /        \ i_aload1               |
+             *                iadd                                   |                            
+             *                 |   \ iconst 1                        |
+             *                 |                                     |
+             *                 |                                  FieldArrayElementIncrement(pre)
+             *                 |    / getfield - aload               |
+             *                iastore -  iload                       |                            
+             *                 |    \ [fieldArrayElementPlusOne]     |
+             *                 |                                     |       
+             *                 B                                     B
+             * </pre>
+             */
+            @Override public Instruction transform(ExpressionList _expressionList, Instruction i) {
+
+               InstructionMatch result = null;
+               if ((result = InstructionPattern.fieldArrayElementPlusOne.matches(i,
+                     InstructionPattern.longHandFieldArrayElementIncrement)).ok) {
+
+                  Instruction addRaw = i;
+                  Instruction assignArrayRaw = i.getNextExpr();
+                  //   I_IADD add = (I_IADD) addRaw.getReal();
+                  AssignToArrayElement assignArray = (AssignToArrayElement) assignArrayRaw.getReal();
+                  FieldArrayElementIncrement inlineAssign = new FieldArrayElementIncrement(MethodModel.this, assignArray, true,
+                        true);
+                  _expressionList.replaceInclusive(addRaw, assignArrayRaw, inlineAssign);
+                  return (inlineAssign);
+
+               }
+
+               return (null);
+            }
+
+         },
+         new InstructionTransformer("field array element pre decrement with nested index (local variable) pre decrement"){
+            /**
+             * <pre>
+             *                 A                                     A
+             *                 |            / getfield - aload       |
+             *                 |    / iaload                         |
+             *                 |   /        \ i_aload1               |
+             *                isub                                   |                            
+             *                 |   \ iconst 1                        |
+             *                 |                                     |
+             *                 |                                  FieldArrayElementIncrement(pre)
+             *                 |    / getfield - aload               |
+             *                iastore -  iload                       |                            
+             *                 |    \ [fieldArrayElementMinusOne]    |
+             *                 |                                     |       
+             *                 B                                     B
+             * </pre>
+             */
+            @Override public Instruction transform(ExpressionList _expressionList, Instruction i) {
+
+               InstructionMatch result = null;
+               if ((result = InstructionPattern.fieldArrayElementMinusOne.matches(i,
+                     InstructionPattern.longHandFieldArrayElementDecrement)).ok) {
+
+                  Instruction subRaw = i;
+                  Instruction assignArrayRaw = i.getNextExpr();
+                  //   I_IADD add = (I_IADD) addRaw.getReal();
+                  AssignToArrayElement assignArray = (AssignToArrayElement) assignArrayRaw.getReal();
+                  FieldArrayElementIncrement inlineAssign = new FieldArrayElementIncrement(MethodModel.this, assignArray, false,
+                        true);
+                  _expressionList.replaceInclusive(subRaw, assignArrayRaw, inlineAssign);
+                  return (inlineAssign);
+
+               }
+               return (null);
+            }
+
+         },
+         new InstructionTransformer("field array element post inccrement with nested index (local variable) "){
+
+            @Override public Instruction transform(ExpressionList _expressionList, Instruction i) {
+
+               InstructionMatch result = null;
+               if ((result = InstructionPattern.fieldArrayElementAccess.matches(i,
+                     InstructionPattern.longHandFieldArrayElementIncrement)).ok) {
+                  /**
+                   * <pre>
+                   *                 A                                     A              
+                   *                 |     / getfield<f> - aload           |
+                   *                iaload                                 |
+                   *                 |     \ i_load                        |                    
+                   *                 |                                 FieldArrayElementIncrement(post)
+                   *                 |    / getfield - aload               |
+                   *                iastore -  iload                       |                            
+                   *                 |    \ [fieldArrayElementPlusOne]     |
+                   *                 |                                     |           
+                   *                 B                                     B
+                   *                 
+                   *  
+                   * </pre>
+                   */
+                  Instruction accessArrayRaw = i;
+                  Instruction assignArrayRaw = i.getNextExpr();
+                  AccessArrayElement accessArray = (AccessArrayElement) accessArrayRaw.getReal();
+                  AssignToArrayElement assignArray = (AssignToArrayElement) assignArrayRaw.getReal();
+                  AccessField accessField1 = (AccessField) accessArray.getArrayRef().getReal();
+                  AccessField accessField2 = (AccessField) assignArray.getArrayRef().getReal();
+                  if (accessField1.getConstantPoolFieldIndex() == accessField2.getConstantPoolFieldIndex()) {
+                     // we accessing the same field at least
+                     //AccessLocalVariable accessLocalVariable1 = (AccessLocalVariable) accessArray.getArrayIndex().getReal();
+                     //AccessLocalVariable accessLocalVariable2 = (AccessLocalVariable) assignArray.getArrayIndex().getReal();
+                     //  if (accessLocalVariable1.getLocalVariableTableIndex() == accessLocalVariable2.getLocalVariableTableIndex()) {
+                     // and both arrays are referencing the array element using the same variable
+                     FieldArrayElementIncrement inlineAssign = new FieldArrayElementIncrement(MethodModel.this, assignArray, true,
+                           false);
+                     _expressionList.replaceInclusive(accessArrayRaw, assignArrayRaw, inlineAssign);
+                     return (inlineAssign);
+                     // }
+                  }
+
+               }
+
+               return (null);
+            }
+
+         },
+         new InstructionTransformer("field array element post decrement with nested index (local variable) "){
+            /**
+             * <pre>
+             *                 A                                     A              
+             *                 |     / getfield<f> - aload           |
+             *                iaload                                 |
+             *                 |     \ i_load                        |                    
+             *                 |                                 FieldArrayElementIncrement(post)
+             *                 |    / getfield - aload               |
+             *                iastore -  iload                       |                            
+             *                 |    \ [fieldArrayElementMinusOne]    |
+             *                 |                                     |           
+             *                 B                                     B
+             *                 
+             *  
+             * </pre>
+             */
+            @Override public Instruction transform(ExpressionList _expressionList, Instruction i) {
+
+               InstructionMatch result = null;
+               if ((result = InstructionPattern.fieldArrayElementAccess.matches(i,
+                     InstructionPattern.longHandFieldArrayElementDecrement)).ok) {
+
+                  Instruction accessArrayRaw = i;
+                  Instruction assignArrayRaw = i.getNextExpr();
+                  AccessArrayElement accessArray = (AccessArrayElement) accessArrayRaw.getReal();
+                  AssignToArrayElement assignArray = (AssignToArrayElement) assignArrayRaw.getReal();
+                  AccessField accessField1 = (AccessField) accessArray.getArrayRef().getReal();
+                  AccessField accessField2 = (AccessField) assignArray.getArrayRef().getReal();
+                  if (accessField1.getConstantPoolFieldIndex() == accessField2.getConstantPoolFieldIndex()) {
+                     // we accessing the same field at least
+                     AccessLocalVariable accessLocalVariable1 = (AccessLocalVariable) accessArray.getArrayIndex().getReal();
+                     AccessLocalVariable accessLocalVariable2 = (AccessLocalVariable) assignArray.getArrayIndex().getReal();
+                     if (accessLocalVariable1.getLocalVariableTableIndex() == accessLocalVariable2.getLocalVariableTableIndex()) {
+                        // and both arrays are referencing the array element using the same variable
+                        FieldArrayElementIncrement inlineAssign = new FieldArrayElementIncrement(MethodModel.this, assignArray,
+                              false, false);
+                        _expressionList.replaceInclusive(accessArrayRaw, assignArrayRaw, inlineAssign);
+                        return (inlineAssign);
+                     }
+                  }
+
+               }
+               return (null);
+            }
+
+         },
+         new InstructionTransformer("inline assign (for method call or logical expression)"){
+            /**
+             * <pre>
+             *                 A                                     A
+             *                 |                                     |
+             *          0, 0  invoke<n>                              |
+             *                 |       / invoke()               InlineAssign(istore<?>, invoke)
+             *         +1, 0  istore<?>                              |
+             *                 |                                     |           
+             *                 B                                     B
+             * </pre>
+             */
+
+            @Override public Instruction transform(ExpressionList _expressionList, Instruction i) {
+
+               InstructionMatch result = null;
+               if ((result = InstructionPattern.methodCall.matches(i, InstructionPattern.assignToLocalVariable)).ok) {
+
+                  Instruction invoke = i;
+
+                  AssignToLocalVariable assign = (AssignToLocalVariable) i.getNextExpr();
+
+                  InlineAssignInstruction inlineAssign = new InlineAssignInstruction(MethodModel.this, assign, (Instruction) invoke);
+                  _expressionList.replaceInclusive((Instruction) invoke, (Instruction) assign, inlineAssign);
+                  return (inlineAssign);
+
+               }
+               return (null);
+            }
+
+         },
+         new InstructionTransformer("incline assign from constant (method call or logical expression)"){
+            /**
+             * <pre>
+             *                 A                                     A
+             *                 |                                     |
+             *          0, 0  invoke<n>                              |
+             *                 |       / invoke()               InlineAssign(istore<?>, invoke)
+             *         +1, 0  istore<?>                              |
+             *                 |                                     |           
+             *                 B                                     B
+             * </pre>
+             */
+
+            @Override public Instruction transform(ExpressionList _expressionList, Instruction i) {
+
+               InstructionMatch result = null;
+
+               if ((result = InstructionPattern.constant.matches(i, InstructionPattern.assignToLocalVariable)).ok) {
+
+                  Instruction constant = i;
+
+                  AssignToLocalVariable assign = (AssignToLocalVariable) i.getNextExpr();
+
+                  InlineAssignInstruction inlineAssign = new InlineAssignInstruction(MethodModel.this, assign,
+                        (Instruction) constant);
+                  _expressionList.replaceInclusive((Instruction) constant, (Instruction) assign, inlineAssign);
+                  return (inlineAssign);
+
+               }
+
+               return (null);
+            }
+
+         },
+         new InstructionTransformer("inline array assignment as part of a method call"){
+            /**
+             * <pre>
+             *                 A                                     A
+             *                 |                                     |
+             *          0, 0  invoke<n>                              |
+             *                 |       / invoke()               InlineAssign(istore<?>, invoke)
+             *         +1, 0  iastore<?>                              |
+             *                 |                                     |           
+             *                 B                                     B
+             * </pre>
+             */
+            @Override public Instruction transform(ExpressionList _expressionList, Instruction i) {
+
+               InstructionMatch result = null;
+               if ((result = InstructionPattern.methodCall.matches(i, InstructionPattern.assignToArrayElement)).ok) {
+
+                  Instruction invoke = i;
+
+                  AssignToArrayElement assign = (AssignToArrayElement) i.getNextExpr();
+
+                  FieldArrayElementAssign inlineAssign = new FieldArrayElementAssign(MethodModel.this, assign, (Instruction) invoke);
+                  _expressionList.replaceInclusive((Instruction) invoke, (Instruction) assign, inlineAssign);
+                  return (inlineAssign);
+
+               }
+
+               return (null);
+            }
+
+         },
+         new InstructionTransformer("inline array element increment as as part of a method call "){
+            /**
+             * <pre>
+             *                 A                                     A
+             *                 |                                     |
+             *          0, 0  invoke<n>                              |
+             *                 |       / invoke()               InlineAssign(istore<?>, invoke)
+             *         +1, 0  iastore<?>                              |
+             *                 |                                     |           
+             *                 B                                     B
+             * </pre>
+             */
+            @Override public Instruction transform(ExpressionList _expressionList, Instruction i) {
+
+               InstructionMatch result = null;
+               if ((result = InstructionPattern.assignToArrayElement.matches(i,
+                     InstructionPattern.longHandFieldArrayElementIncrement)).ok) {
+
+                  Instruction invoke = i;
+
+                  AssignToArrayElement assign = (AssignToArrayElement) i.getNextExpr();
+
+                  FieldArrayElementAssign inlineAssign = new FieldArrayElementAssign(MethodModel.this, assign, (Instruction) invoke);
+                  _expressionList.replaceInclusive((Instruction) invoke, (Instruction) assign, inlineAssign);
+
+                  return (inlineAssign);
+
+               }
+
+               return (null);
+            }
+
+         }
+
+   };
+
+   void applyTransformations(ExpressionList _expressionList, final Instruction _instruction, final Instruction _operandStart)
+         throws ClassParseException {
+
+      if (logger.isLoggable(Level.FINE)) {
+
+         System.out.println("We are looking at " + _instruction + " which wants to consume " + _instruction.getStackConsumeCount()
+               + " operands");
+      }
+      boolean txformed = false;
+
+      /**
+       * Here we look for multi-assigns
+       * i.e 
+       * 
+       * a=b=c=<exp>;
+       */
+      if (_instruction instanceof AssignToLocalVariable && _operandStart.producesStack()
+            && _operandStart.getNextExpr() instanceof AssignToLocalVariable) {
+         Instruction assignFirst = _operandStart.getNextExpr();
+         Instruction assign = assignFirst;
+         int count = 0;
+         while (assign != null && assign instanceof AssignToLocalVariable) {
+            assign = assign.getNextExpr();
+            count++;
+         }
+         if (assign == null) {
+            Instruction newOne = new MultiAssignInstruction(this, _operandStart, assignFirst, assign);
+            _expressionList.replaceInclusive(_operandStart, assign, newOne);
+            txformed = true;
+         }
+      }
+
+      if (!txformed) {
+         boolean again = false;
+         for (Instruction i = _operandStart; i != null; i = again ? i : i.getNextExpr()) {
+            again = false;
+
+            for (InstructionTransformer txformer : transformers) {
+               Instruction newI = txformer.transform(_expressionList, i);
+               if (newI != null) {
+                  i = newI;
+                  again = true;
+                  txformed = true;
+                  break;
+               }
+            }
+
+         }
+
+      }
+
+      if (txformed) {
+         if (logger.isLoggable(Level.FINE)) {
+
+            System.out.println("We are looking at " + _instruction + " which wants to consume "
+                  + _instruction.getStackConsumeCount() + " operands");
+         }
+      } else {
+         throw new ClassParseException(_instruction, ClassParseException.TYPE.OPERANDCONSUMERPRODUCERMISSMATCH);
+      }
+
+   }
+
+   /**
+    * Determine if this method is a getter and record the accessed field if so
+    */
+   void checkForGetter(Map<Integer, Instruction> pcMap) throws ClassParseException {
+      String methodName = getMethod().getName();
+      String rawVarNameCandidate = null;
+      boolean mightBeSetter = true;
+
+      if (methodName.startsWith("get")) {
+         rawVarNameCandidate = methodName.substring(3);
+      } else if (methodName.startsWith("is")) {
+         rawVarNameCandidate = methodName.substring(2);
+      } else {
+         mightBeSetter = false;
+      }
+
+      // Getters should have 3 bcs: aload_0, getfield, ?return
+      if (mightBeSetter) {
+         if (rawVarNameCandidate != null && pcMap.size() == 3) {
+            String firstLetter = rawVarNameCandidate.substring(0, 1).toLowerCase();
+            String varNameCandidateCamelCased = rawVarNameCandidate.replaceFirst(rawVarNameCandidate.substring(0, 1), firstLetter);
+            String accessedFieldName = null;
+            Instruction instruction = expressionList.getHead();
+
+            if (instruction instanceof Return && (expressionList.getHead() == expressionList.getTail())) {
+               instruction = instruction.getPrevPC();
+               if (instruction instanceof AccessInstanceField) {
+                  FieldEntry field = ((AccessInstanceField) instruction).getConstantPoolFieldEntry();
+                  accessedFieldName = field.getNameAndTypeEntry().getNameUTF8Entry().getUTF8();
+                  if (accessedFieldName.equals(varNameCandidateCamelCased)) {
+
+                     // Verify field type matches return type
+                     String fieldType = field.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8();
+                     String returnType = getMethod().getDescriptor().substring(2);
+                     //System.out.println( "### field type = " + fieldType );
+                     //System.out.println( "### method args = " + returnType );
+                     assert fieldType.length() == 1 && returnType.length() == 1 : " can only use basic type getters";
+
+                     // Allow isFoo style for boolean fields
+                     if ((methodName.startsWith("is") && fieldType.equals("Z")) || (methodName.startsWith("get"))) {
+                        if (fieldType.equals(returnType)) {
+                           if (logger.isLoggable(Level.FINE)) {
+                              logger.fine("Found " + methodName + " as a getter for " + varNameCandidateCamelCased.toLowerCase());
+                           }
+
+                           methodIsGetter = true;
+                           accessorVariableFieldEntry = field;
+                           assert methodIsSetter == false : " cannot be both";
+                        } else {
+                           throw new ClassParseException(ClassParseException.TYPE.BADGETTERTYPEMISMATCH, methodName);
+
+                        }
+                     }
+                  } else {
+                     throw new ClassParseException(ClassParseException.TYPE.BADGETTERNAMEMISMATCH, methodName);
+                  }
+               }
+            } else {
+               throw new ClassParseException(ClassParseException.TYPE.BADGETTERNAMENOTFOUND, methodName);
+            }
+         } else {
+            throw new ClassParseException(ClassParseException.TYPE.BADGETTERNAMENOTFOUND, methodName);
+         }
+      }
+   }
+
+   /**
+    * Determine if this method is a setter and record the accessed field if so
+    */
+   void checkForSetter(Map<Integer, Instruction> pcMap) throws ClassParseException {
+      String methodName = getMethod().getName();
+      if (methodName.startsWith("set")) {
+         String rawVarNameCandidate = methodName.substring(3);
+         String firstLetter = rawVarNameCandidate.substring(0, 1).toLowerCase();
+         String varNameCandidateCamelCased = rawVarNameCandidate.replaceFirst(rawVarNameCandidate.substring(0, 1), firstLetter);
+         String accessedFieldName = null;
+         Instruction instruction = expressionList.getHead();
+
+         // setters should be aload_0, ?load_1, putfield, return
+         if (instruction instanceof AssignToInstanceField && expressionList.getTail() instanceof Return && pcMap.size() == 4) {
+            Instruction prev = instruction.getPrevPC();
+            if (prev instanceof AccessLocalVariable) {
+               FieldEntry field = ((AssignToInstanceField) instruction).getConstantPoolFieldEntry();
+               accessedFieldName = field.getNameAndTypeEntry().getNameUTF8Entry().getUTF8();
+               if (accessedFieldName.equals(varNameCandidateCamelCased)) {
+
+                  // Verify field type matches setter arg type
+                  String fieldType = field.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8();
+                  String setterArgType = getMethod().getDescriptor().substring(1, 2);
+
+                  //System.out.println( "### field type = " + fieldType );
+                  //System.out.println( "### setter type = " + setterArgType );
+                  assert fieldType.length() == 1 : " can only use basic type getters";
+
+                  if (fieldType.equals(setterArgType)) {
+                     if (logger.isLoggable(Level.FINE)) {
+                        logger.fine("Found " + methodName + " as a setter for " + varNameCandidateCamelCased.toLowerCase()
+                              + " of type " + fieldType);
+                     }
+
+                     methodIsSetter = true;
+                     accessorVariableFieldEntry = field;
+
+                     // Setters use putfield which will miss the normal store check
+                     if (fieldType.equals("B") || fieldType.equals("Z")) {
+                        usesByteWrites = true;
+                     }
+
+                     assert methodIsGetter == false : " cannot be both";
+                  } else {
+                     throw new ClassParseException(ClassParseException.TYPE.BADSETTERTYPEMISMATCH, methodName);
+                  }
+               } else {
+                  throw new ClassParseException(ClassParseException.TYPE.BADSETTERTYPEMISMATCH, methodName);
+               }
+            }
+         }
+      }
+   }
+
+   // The entrypoint is used to make checks on object accessors
+   Entrypoint entrypoint = null;
+
+   MethodModel(ClassModelMethod _method, Entrypoint _entrypoint) throws AparapiException {
+      entrypoint = _entrypoint;
+      init(_method);
+   }
+
+   MethodModel(ClassModelMethod _method) throws AparapiException {
+      init(_method);
+   }
+
+   private void init(ClassModelMethod _method) throws AparapiException {
+      try {
+         method = _method;
+         this.expressionList = new ExpressionList(this);
+
+         // check if we have any exception handlers
+         int exceptionsSize = method.getCodeEntry().getExceptionPoolEntries().size();
+         if (exceptionsSize > 0) {
+            if (logger.isLoggable(Level.FINE)) {
+               logger.fine("exception size for " + method + " = " + exceptionsSize);
+            }
+            throw new ClassParseException(ClassParseException.TYPE.EXCEPTION);
+         }
+
+         // check if we have any local variables which are arrays.  This is an attempt to avoid aliasing field arrays
+
+         for (LocalVariableInfo localVariableInfo : method.getLocalVariableTableEntry()) {
+            final boolean DISALLOWARRAYLOCALVAR = false;
+            if (DISALLOWARRAYLOCALVAR && localVariableInfo.getVariableDescriptor().startsWith("[")) {
+               throw new ClassParseException(ClassParseException.TYPE.ARRAYLOCALVARIABLE);
+            }
+            if (localVariableInfo.getVariableDescriptor().equals("C")) {
+               throw new ClassParseException(ClassParseException.TYPE.CHARLOCALVARIABLE);
+            }
+
+         }
+
+         // We are going to make 4 passes.
+
+         // Pass #1 create a linked list of instructions from head to tail
+         Map<Integer, Instruction> pcMap = createListOfInstructions();
+
+         // pass #2 build branch graph
+         buildBranchGraphs(pcMap);
+
+         // pass #3 build branch graph
+         deoptimizeReverseBranches();
+
+         // pass #4
+
+         foldExpressions();
+
+         // Accessor conversion only works on member object arrays
+         if (entrypoint != null && _method.getClassModel() != entrypoint.getClassModel()) {
+            if (logger.isLoggable(Level.FINE)) {
+               logger.fine("Considering accessor call: " + getName());
+            }
+            checkForGetter(pcMap);
+            checkForSetter(pcMap);
+         }
+
+         // In order to allow inline access of object member fields, postpone this check
+         //if ((!Config.enablePUTFIELD) && usesPutfield && !isSetter()) {
+         //   throw new ClassParseException("We don't support putfield instructions beyond simple setters");
+         //}
+
+         if (logger.isLoggable(Level.FINE)) {
+
+            System.out.println("end \n" + expressionList.dumpDiagram(null));
+
+         }
+         if (Config.instructionListener != null) {
+            Config.instructionListener.showAndTell("end", expressionList.getHead(), null);
+         }
+      } catch (Throwable _t) {
+         if (_t instanceof ClassParseException) {
+            _t.printStackTrace();
+            throw (ClassParseException) _t;
+         }
+         throw new ClassParseException(_t);
+
+      }
+   }
+
+   LocalVariableTableEntry getLocalVariableTableEntry() {
+      return (method.getLocalVariableTableEntry());
+   }
+
+   ConstantPool getConstantPool() {
+      return (method.getConstantPool());
+   }
+
+   LocalVariableInfo getLocalVariable(int _pc, int _index) {
+      return (method.getLocalVariable(_pc, _index));
+   }
+
+   String getSimpleName() {
+      return (method.getName());
+   }
+
+   /*
+    * @return the fully qualified name such as "com_amd_javalabs_opencl_demo_PaternityTest$SimpleKernel__actuallyDoIt"
+    */
+   String getName() {
+      return (method.getClassModel().getMethod(method.getName(), method.getDescriptor()).getClassModel().getClassWeAreModelling()
+            .getName().replace('.', '_')
+            + "__" + method.getName());
+   }
+
+   String getReturnType() {
+      String returnType = method.getDescriptorUTF8Entry().getUTF8();
+      int index = returnType.indexOf(")");
+      return (returnType.substring(index + 1));
+   }
+
+   List<MethodCall> getMethodCalls() {
+      List<MethodCall> methodCalls = new ArrayList<MethodCall>();
+
+      for (Instruction i = getPCHead(); i != null; i = i.getNextPC()) {
+         if (i instanceof MethodCall) {
+            MethodCall methodCall = (MethodCall) i;
+            methodCalls.add(methodCall);
+         }
+      }
+      return (methodCalls);
+   }
+
+   Instruction getPCHead() {
+      return (pcHead);
+   }
+
+   Instruction getExprHead() {
+      return (expressionList.getHead());
+   }
+
+}
diff --git a/com.amd.aparapi/src/java/com/amd/aparapi/UnsafeWrapper.java b/com.amd.aparapi/src/java/com/amd/aparapi/UnsafeWrapper.java
new file mode 100644
index 00000000..2d14f47e
--- /dev/null
+++ b/com.amd.aparapi/src/java/com/amd/aparapi/UnsafeWrapper.java
@@ -0,0 +1,414 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * A wrapper around sun.misc.Unsafe for handling atomic operations, copies from fields to arrays and vice versa.
+ * 
+ * We avoid using <code>sun.misc.Unsafe</code> directly using reflection, mostly just to avoid getting 'unsafe' compiler errors. 
+ * 
+ * This might need to be changed if we start to see performance issues.
+ *
+ * @author gfrost
+ *
+ */
+
+class UnsafeWrapper{
+
+   private static Object unsafe;
+
+   private static Method getIntVolatileMethod;
+
+   private static Method arrayBaseOffsetMethod;
+
+   private static Method arrayIndexScaleMethod;
+
+   private static Method getObjectMethod;
+
+   private static Method getIntMethod;
+
+   private static Method getFloatMethod;
+
+   private static Method getByteMethod;
+
+   private static Method getBooleanMethod;
+
+   private static Method getLongMethod;
+
+   private static Method objectFieldOffsetMethod;
+
+   private static Method putBooleanMethod;
+
+   private static Method putIntMethod;
+
+   private static Method putFloatMethod;
+
+   private static Method putDoubleMethod;
+
+   private static Method putByteMethod;
+
+   private static Method putLongMethod;
+
+   private static Method compareAndSwapIntMethod;
+   static {
+      try {
+         Class<?> uc = Class.forName("sun.misc.Unsafe");
+
+         Field field = uc.getDeclaredField("theUnsafe");
+         field.setAccessible(true);
+         unsafe = field.get(uc);
+         getIntVolatileMethod = uc.getDeclaredMethod("getIntVolatile", Object.class, long.class);
+         arrayBaseOffsetMethod = uc.getDeclaredMethod("arrayBaseOffset", Class.class);
+         arrayIndexScaleMethod = uc.getDeclaredMethod("arrayIndexScale", Class.class);
+         getObjectMethod = uc.getDeclaredMethod("getObject", Object.class, long.class);
+         getIntMethod = uc.getDeclaredMethod("getInt", Object.class, long.class);
+         getFloatMethod = uc.getDeclaredMethod("getFloat", Object.class, long.class);
+         getByteMethod = uc.getDeclaredMethod("getByte", Object.class, long.class);
+         getBooleanMethod = uc.getDeclaredMethod("getBoolean", Object.class, long.class);
+         getLongMethod = uc.getDeclaredMethod("getLong", Object.class, long.class);
+         objectFieldOffsetMethod = uc.getDeclaredMethod("objectFieldOffset", Field.class);
+         putBooleanMethod = uc.getDeclaredMethod("putBoolean", Object.class, long.class, boolean.class);
+         putIntMethod = uc.getDeclaredMethod("putInt", Object.class, long.class, int.class);
+         putFloatMethod = uc.getDeclaredMethod("putFloat", Object.class, long.class, float.class);
+         putDoubleMethod = uc.getDeclaredMethod("putDouble", Object.class, long.class, double.class);
+         putLongMethod = uc.getDeclaredMethod("putLong", Object.class, long.class, long.class);
+         putByteMethod = uc.getDeclaredMethod("putByte", Object.class, long.class, byte.class);
+         compareAndSwapIntMethod = uc.getDeclaredMethod("compareAndSwapInt", Object.class, long.class, int.class, int.class);
+      } catch (SecurityException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (NoSuchFieldException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalArgumentException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (ClassNotFoundException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (NoSuchMethodException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+
+   }
+
+   static int atomicAdd(int[] _arr, int _index, int _delta) {
+      if (_index < 0 || _index >= _arr.length)
+         throw new IndexOutOfBoundsException("index " + _index);
+
+      long rawIndex = intArrayBase + (long) _index * intArrayScale;
+      while (true) {
+         int current;
+         try {
+            current = (Integer) getIntVolatileMethod.invoke(unsafe, _arr, rawIndex);
+            int next = current + _delta;
+            if ((Boolean) compareAndSwapIntMethod.invoke(unsafe, _arr, rawIndex, current, next)) {
+               return current;
+            }
+         } catch (IllegalArgumentException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+         } catch (IllegalAccessException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+         } catch (InvocationTargetException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+         }
+
+      }
+
+   }
+
+   static int arrayBaseOffset(Class<?> _arrayClass) {
+      int offset = 0;
+
+      try {
+         offset = (Integer) (arrayBaseOffsetMethod.invoke(unsafe, _arrayClass));
+      } catch (IllegalArgumentException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (InvocationTargetException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+
+      return (offset);
+   }
+
+   static int arrayIndexScale(Class<?> _arrayClass) {
+      int scale = 0;
+      try {
+         scale = (Integer) (arrayIndexScaleMethod.invoke(unsafe, _arrayClass));
+      } catch (IllegalArgumentException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (InvocationTargetException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+      return scale;
+   }
+
+   private static int intArrayBase = arrayBaseOffset(int[].class);
+
+   private static int intArrayScale = arrayIndexScale(int[].class);
+
+   static Object getObject(Object _object, long _offset) {
+      Object object = null;
+      try {
+         object = getObjectMethod.invoke(unsafe, _object, _offset);
+      } catch (IllegalArgumentException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (InvocationTargetException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+      return (object);
+   }
+
+   static int getInt(Object _object, long _offset) {
+      int value = 0;
+      try {
+         value = (Integer) getIntMethod.invoke(unsafe, _object, _offset);
+      } catch (IllegalArgumentException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (InvocationTargetException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+      return value;
+   }
+
+   static float getFloat(Object _object, long _offset) {
+      float value = 0;
+      try {
+         value = (Float) getFloatMethod.invoke(unsafe, _object, _offset);
+      } catch (IllegalArgumentException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (InvocationTargetException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+      return value;
+   }
+
+   static byte getByte(Object _object, long _offset) {
+      byte value = 0;
+      try {
+         value = (Byte) getByteMethod.invoke(unsafe, _object, _offset);
+      } catch (IllegalArgumentException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (InvocationTargetException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+      return value;
+   }
+
+   static boolean getBoolean(Object _object, long _offset) {
+      boolean value = false;
+      try {
+         value = (Boolean) getBooleanMethod.invoke(unsafe, _object, _offset);
+      } catch (IllegalArgumentException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (InvocationTargetException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+      return value;
+   }
+
+   static long getLong(Object _object, long _offset) {
+      long value = 0;
+      try {
+         value = (Long) getLongMethod.invoke(unsafe, _object, _offset);
+      } catch (IllegalArgumentException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (InvocationTargetException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+      return value;
+   }
+
+   static void putBoolean(Object _object, long _offset, boolean _boolean) {
+      try {
+         putBooleanMethod.invoke(unsafe, _object, _offset, _boolean);
+      } catch (IllegalArgumentException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (InvocationTargetException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+   }
+
+   static void putFloat(Object _object, long _offset, float _float) {
+      try {
+         putFloatMethod.invoke(unsafe, _object, _offset, _float);
+      } catch (IllegalArgumentException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (InvocationTargetException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+   }
+
+   static void putInt(Object _object, long _offset, int _int) {
+      try {
+         putIntMethod.invoke(unsafe, _object, _offset, _int);
+      } catch (IllegalArgumentException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (InvocationTargetException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+   }
+
+   static void putDouble(Object _object, long _offset, double _double) {
+      try {
+         putDoubleMethod.invoke(unsafe, _object, _offset, _double);
+      } catch (IllegalArgumentException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (InvocationTargetException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+   }
+
+   static void putByte(Object _object, long _offset, byte _byte) {
+      try {
+         putByteMethod.invoke(unsafe, _object, _offset, _byte);
+      } catch (IllegalArgumentException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (InvocationTargetException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+   }
+
+   static void putLong(Object _object, long _offset, long _long) {
+      try {
+         putLongMethod.invoke(unsafe, _object, _offset, _long);
+      } catch (IllegalArgumentException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (InvocationTargetException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+   }
+
+   static long objectFieldOffset(Field _field) {
+      long offset = 0l;
+      try {
+         offset = (Long) objectFieldOffsetMethod.invoke(unsafe, _field);
+      } catch (IllegalArgumentException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (InvocationTargetException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+      return offset;
+   }
+}
diff --git a/examples/effects/.classpath b/examples/effects/.classpath
new file mode 100644
index 00000000..2b3d4294
--- /dev/null
+++ b/examples/effects/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.amd.aparapi"/>
+	<classpathentry kind="output" path="classes"/>
+</classpath>
diff --git a/examples/effects/.project b/examples/effects/.project
new file mode 100644
index 00000000..525cddc8
--- /dev/null
+++ b/examples/effects/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>effects</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/examples/effects/build.xml b/examples/effects/build.xml
new file mode 100644
index 00000000..8415999c
--- /dev/null
+++ b/examples/effects/build.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+
+<project name="effects" default="build" basedir=".">
+
+   <path id="compiler.class.path">
+      <pathelement path="../../com.amd.aparapi/aparapi.jar"/>
+   </path>
+
+   <path id="runtime.class.path" cache="true">
+      <path refid="compiler.class.path"/>
+      <pathelement path="${ant.project.name}.jar"/>
+   </path>
+
+   <target name="build" depends="clean">
+      <mkdir dir="classes"/>
+      <javac srcdir="src" destdir="classes" debug="on" includeantruntime="false">
+         <classpath refid="compiler.class.path"/>
+      </javac>
+      <jar jarfile="${ant.project.name}.jar" basedir="classes"/>
+   </target>
+
+   <target name="clean">
+      <delete dir="classes"/>
+      <delete file="${ant.project.name}.jar"/>
+   </target>
+
+   <target name="run" >
+      <java classname="com.amd.aparapi.examples.effects.Main" fork="true">
+         <classpath refid="runtime.class.path"/>
+         <sysproperty key="java.library.path" path="..\..\com.amd.aparapi.jni"/>
+         <sysproperty key="com.amd.aparapi.executionMode" value="GPU"/>
+      </java>
+   </target>
+
+</project>
diff --git a/examples/effects/src/com/amd/aparapi/examples/effects/Main.java b/examples/effects/src/com/amd/aparapi/examples/effects/Main.java
new file mode 100644
index 00000000..c5f53c8a
--- /dev/null
+++ b/examples/effects/src/com/amd/aparapi/examples/effects/Main.java
@@ -0,0 +1,270 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+
+package com.amd.aparapi.examples.effects;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionAdapter;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+
+import com.amd.aparapi.Kernel;
+
+/**
+ * An example Aparapi application which displays a view of the Mandelbrot set and lets the user zoom in to a particular point. 
+ * 
+ * When the user clicks on the view, this example application will zoom in to the clicked point and zoom out there after.
+ * On GPU, additional computing units will offer a better viewing experience. On the other hand on CPU, this example 
+ * application might suffer with sub-optimal frame refresh rate as compared to GPU. 
+ *  
+ * @author gfrost
+ *
+ */
+
+public class Main{
+
+   /**
+    * An Aparapi Kernel implementation for creating a scaled view of the mandelbrot set.
+    *  
+    * @author gfrost
+    *
+    */
+
+   public static class MouseTrackKernel extends Kernel{
+
+      /** RGB buffer used to store the screen image. This buffer holds (width * height) RGB values. */
+      final private int rgb[];
+
+      /** image width. */
+      final private int width;
+
+      /**  image height. */
+      final private int height;
+
+      /** Palette used for points */
+      final private int pallette[];
+
+      /** Maximum iterations we will check for. */
+      final private int maxIterations;
+
+      /** Mutable values of scale, offsetx and offsety so that we can modify the zoom level and position of a view. */
+
+      final private float[] offsetx;
+
+      final private float[] offsety;
+
+      final private int trail;
+
+      /**
+       * Initialize the Kernel.
+       *  
+       * @param _width Mandelbrot image width
+       * @param _height Mandelbrot image height
+       * @param _rgb Mandelbrot image RGB buffer
+       * @param _pallette Mandelbrot image palette
+       */
+      public MouseTrackKernel(int _width, int _height, int[] _rgb, int[] _pallette, float[] _offsetx, float[] _offsety) {
+         width = _width;
+         height = _height;
+         rgb = _rgb;
+         pallette = _pallette;
+         maxIterations = pallette.length - 1;
+         offsetx = _offsetx;
+         offsety = _offsety;
+         trail = offsetx.length;
+      }
+
+      @Override public void run() {
+
+         /** Determine which RGB value we are going to process (0..RGB.length). */
+         int gid = getGlobalId();
+
+         /** Translate the gid into an x an y value. */
+         float x = (gid % width);
+
+         float y = (gid / height);
+         
+         float minr = 1024f;
+
+       
+         for (int i = 0; i < trail; i++) {
+
+            float dx = x - offsetx[i];
+            float dy = y - offsety[i];
+            minr = min(sqrt(dx * dx + dy * dy), minr);
+            
+           
+           
+         }
+         int value = (int)minr;
+
+         int newValue = min(value, maxIterations);
+
+         rgb[gid] = pallette[newValue];
+
+      }
+
+   }
+
+   /** User selected zoom-in point on the Mandelbrot view. */
+   public static volatile Point to = null;
+
+   @SuppressWarnings("serial") public static void main(String[] _args) {
+
+      JFrame frame = new JFrame("MandelBrot");
+
+      /** Width of Mandelbrot view. */
+      final int width = 1024;
+
+      /** Height of Mandelbrot view. */
+      final int height = 1024;
+
+      /** Maximum iterations for Mandelbrot. */
+      final int maxIterations = 128;
+
+      /** Palette which maps iteration values to RGB values. */
+      final int pallette[] = new int[maxIterations + 1];
+      
+      final float trailx[] = new float[64];
+      final float traily[] = new float[trailx.length];
+
+      //Initialize palette values
+      for (int i = 0; i < maxIterations; i++) {
+         float h = i / (float) maxIterations;
+         float b = 1.0f - h * h;
+         pallette[i] = Color.HSBtoRGB(h, 1f, b);
+      }
+
+      /** Image for Mandelbrot view. */
+      final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+      final BufferedImage offscreen = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+      // Draw Mandelbrot image
+      JComponent viewer = new JComponent(){
+         @Override public void paintComponent(Graphics g) {
+
+            g.drawImage(image, 0, 0, width, height, this);
+         }
+      };
+
+      // Set the size of JComponent which displays Mandelbrot image
+      viewer.setPreferredSize(new Dimension(width, height));
+
+      final Object doorBell = new Object();
+
+      // Mouse listener which reads the user clicked zoom-in point on the Mandelbrot view 
+      viewer.addMouseMotionListener(new MouseMotionAdapter(){
+
+         @Override public void mouseMoved(MouseEvent e) {
+            to = e.getPoint();
+            // System.out.println(to);
+            synchronized (doorBell) {
+               doorBell.notify();
+            }
+         }
+      });
+
+      // Swing housework to create the frame
+      frame.getContentPane().add(viewer);
+      frame.pack();
+      frame.setLocationRelativeTo(null);
+      frame.setVisible(true);
+
+      // Extract the underlying RGB buffer from the image.
+      // Pass this to the kernel so it operates directly on the RGB buffer of the image
+      final int[] rgb = ((DataBufferInt) offscreen.getRaster().getDataBuffer()).getData();
+      final int[] imageRgb = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
+      // Create a Kernel passing the size, RGB buffer and the palette.
+
+   
+      final MouseTrackKernel kernel = new MouseTrackKernel(width, height, rgb, pallette, trailx, traily);
+
+      for (int i = 0; i < trailx.length; i++) {
+         trailx[i] = (float) width / 2;
+         traily[i] = (float) width / 2;
+      }
+      int trailer = 0;
+      kernel.execute(width * height);
+      System.arraycopy(rgb, 0, imageRgb, 0, rgb.length);
+      viewer.repaint();
+
+      // Report target execution mode: GPU or JTP (Java Thread Pool).
+      System.out.println("Execution mode=" + kernel.getExecutionMode());
+
+      // Window listener to dispose Kernel resources on user exit.
+      frame.addWindowListener(new WindowAdapter(){
+         public void windowClosing(WindowEvent _windowEvent) {
+            kernel.dispose();
+            System.exit(0);
+         }
+      });
+
+      // Wait until the user selects a zoom-in point on the Mandelbrot view.
+      while (true) {
+
+         // Wait for the user to move somwhere
+         while (to == null) {
+            synchronized (doorBell) {
+               try {
+                  doorBell.wait();
+               } catch (InterruptedException ie) {
+                  ie.getStackTrace();
+               }
+            }
+         }
+         trailx[trailer % trailx.length] = (float) to.x;
+         traily[trailer % traily.length] = (float) to.y;
+         trailer++;
+         kernel.execute(width * height);
+         System.arraycopy(rgb, 0, imageRgb, 0, rgb.length);
+         viewer.repaint();
+
+      }
+
+   }
+
+}
diff --git a/examples/nbody/.classpath b/examples/nbody/.classpath
new file mode 100644
index 00000000..b3420b22
--- /dev/null
+++ b/examples/nbody/.classpath
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.amd.aparapi"/>
+	<classpathentry kind="var" path="JOGLDIR/jar/jogl.all.jar"/>
+	<classpathentry kind="var" path="JOGLDIR/jar/gluegen-rt.jar"/>
+	<classpathentry kind="var" path="JOGLDIR/jar/nativewindow.all.jar"/>
+	<classpathentry kind="output" path="classes"/>
+</classpath>
diff --git a/examples/nbody/.project b/examples/nbody/.project
new file mode 100644
index 00000000..f3cf594d
--- /dev/null
+++ b/examples/nbody/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>nbody</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/examples/nbody/build.xml b/examples/nbody/build.xml
new file mode 100644
index 00000000..9a4e9304
--- /dev/null
+++ b/examples/nbody/build.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+
+<project name="nbody" default="build" basedir=".">
+   <property name="jogldir" value="..\..\..\..\jogl\jogl-2.0-b23-20110303-windows-i586"/>
+
+   <path id="compiler.class.path">
+      <pathelement path="../../com.amd.aparapi/aparapi.jar"/>
+      <pathelement path="${jogldir}/jar/jogl.all.jar"/>
+      <pathelement path="${jogldir}/jar/nativewindow.all.jar"/>
+      <pathelement path="${jogldir}/jar/gluegen-rt.jar"/>
+   </path>
+
+   <path id="runtime.class.path" cache="true">
+      <path refid="compiler.class.path"/>
+      <pathelement path="${ant.project.name}.jar"/>
+   </path>
+
+   <target name="check">
+      <fail message="Error:">
+         <condition>
+            <not><isset property="jogldir"/></not>
+         </condition>
+         <![CDATA[
+         You will need to edit build.xml
+
+         At present jogldir is not set.  It needs to point to an jogl install directory.
+         ]]>
+      </fail>
+      <available file="${jogldir}" type="dir" property="jogldir.exists"/>
+      <fail message="Error:">
+         <condition>
+            <not><isset property="jogldir.exists"/></not>
+         </condition>
+         <![CDATA[
+         You will need to edit build.xml
+
+         At present jogldir is set to ${jogldir} but that dir does not exist
+         ]]>
+      </fail>
+      <available file="${jogldir}/jar" type="dir" property="jogldir.jar.exists"/>
+      <available file="${jogldir}/lib" type="dir" property="jogldir.lib.exists"/>
+      <fail message="Error:">
+         <condition>
+            <or>
+               <not><isset property="jogldir.jar.exists"/></not>
+               <not><isset property="jogldir.jar.exists"/></not>
+            </or>
+         </condition>
+         <![CDATA[
+         You will need to edit build.xml
+
+         At present jogldir is set to ${jogldir} but that does not seem to be a valid jogl install. 
+         ]]>
+      </fail>
+   </target>
+
+   <target name="build" depends="clean,check">
+      <mkdir dir="classes"/>
+      <javac srcdir="src" destdir="classes" debug="on" includeantruntime="false">
+         <classpath refid="compiler.class.path"/>
+      </javac>
+      <copy todir="classes/com/amd/aparapi/examples/nbody" file="src/com/amd/aparapi/examples/nbody/particle.jpg"/>
+      <jar jarfile="${ant.project.name}.jar" basedir="classes"/>
+   </target>
+
+   <target name="clean">
+      <delete dir="classes"/>
+      <delete file="${ant.project.name}.jar"/>
+   </target>
+
+   <target name="run" depends="check">
+      <java classname="com.amd.aparapi.examples.nbody.Main" fork="true">
+         <classpath refid="runtime.class.path"/>
+         <sysproperty key="java.library.path" path="..\..\com.amd.aparapi.jni:${jogldir}\lib"/>
+         <sysproperty key="com.amd.aparapi.executionMode" value="GPU"/>
+         <sysproperty key="bodies" value="16384"/>
+         <sysproperty key="height" value="800"/>
+         <sysproperty key="width" value="800"/>
+      </java>
+   </target>
+
+</project>
diff --git a/examples/nbody/nbody.bat b/examples/nbody/nbody.bat
new file mode 100644
index 00000000..c2e4ff1b
--- /dev/null
+++ b/examples/nbody/nbody.bat
@@ -0,0 +1,19 @@
+@echo off
+
+set JOGLDIR=..\..\..\..\jogl\jogl-2.0-b23-20110303-windows-i586
+
+set JOGLJARS=
+set JOGLJARS=%JOGLJARS%;%JOGLDIR%\jar\jogl.all.jar
+set JOGLJARS=%JOGLJARS%;%JOGLDIR%\jar\nativewindow.all.jar
+set JOGLJARS=%JOGLJARS%;%JOGLDIR%\jar\gluegen-rt.jar
+
+java ^
+  -Djava.library.path=..\..\com.amd.aparapi.jni;%JOGLDIR%\lib ^
+  -Dcom.amd.aparapi.executionMode=%1 ^
+  -Dbodies=%2 ^
+  -Dheight=600 ^
+  -Dwidth=600 ^
+  -classpath %JOGLJARS%;..\..\com.amd.aparapi\aparapi.jar;nbody.jar ^
+  com.amd.aparapi.examples.nbody.Main 
+
+
diff --git a/examples/nbody/nbody.sh b/examples/nbody/nbody.sh
new file mode 100644
index 00000000..66e0d28c
--- /dev/null
+++ b/examples/nbody/nbody.sh
@@ -0,0 +1,16 @@
+export JOGLDIR=../../../../jogl/jogl-2.0-b23-20110303-linux-amd64
+
+export JOGLJARS=
+export JOGLJARS=${JOGLJARS}:${JOGLDIR}/jar/jogl.all.jar
+export JOGLJARS=${JOGLJARS}:${JOGLDIR}/jar/nativewindow.all.jar
+export JOGLJARS=${JOGLJARS}:${JOGLDIR}/jar/gluegen-rt.jar
+
+${JAVA_HOME}/bin/java \
+  -Djava.library.path=../../com.amd.aparapi.jni:${JOGLDIR}/lib \
+  -Dcom.amd.aparapi.executionMode=$1 \
+  -Dbodies=$1 \
+  -Dheight=600 \
+  -Dwidth=600 \
+  -classpath ${JOGLJARS}:../../com.amd.aparapi/aparapi.jar:nbody.jar \
+  com.amd.aparapi.examples.nbody.Main 
+
diff --git a/examples/nbody/src/com/amd/aparapi/examples/nbody/Main.java b/examples/nbody/src/com/amd/aparapi/examples/nbody/Main.java
new file mode 100644
index 00000000..12dedcbb
--- /dev/null
+++ b/examples/nbody/src/com/amd/aparapi/examples/nbody/Main.java
@@ -0,0 +1,325 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi.examples.nbody;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.awt.GLCanvas;
+import javax.media.opengl.fixedfunc.GLLightingFunc;
+import javax.media.opengl.glu.GLU;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.WindowConstants;
+
+import com.amd.aparapi.Kernel;
+import com.jogamp.opengl.util.FPSAnimator;
+import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureIO;
+
+public class Main{
+
+
+   public static class NBodyKernel extends Kernel{
+      protected final float delT = .005f;
+
+      protected final float espSqr = 1.0f;
+
+      protected final float mass = 5f;
+
+      private final int bodies;
+
+      private final float[] xyz; // positions xy and z of bodies
+
+      private final float[] vxyz; // velocity component of x,y and z of bodies 
+
+      /**
+       * Constructor initializes xyz and vxyz arrays.
+       * @param _bodies
+       */
+      public NBodyKernel(int _bodies) {
+         bodies = _bodies;
+         xyz = new float[bodies * 3];
+         vxyz = new float[bodies * 3];
+         float maxDist = 20f;
+         for (int body = 0; body < bodies * 3; body += 3) {
+            // If I could remmember some basic algebra I guess I could avoid this loop ;) 
+            // just ensures that the x,y,z is within maxdist radius of origin
+            do {
+               xyz[body + 0] = (float) (Math.random() * 2 * maxDist) - maxDist; //x
+               xyz[body + 1] = (float) (Math.random() * 2 * maxDist) - maxDist; //y
+               xyz[body + 2] = (float) (Math.random() * 2 * maxDist) - maxDist; //z
+            } while (xyz[body + 0] * xyz[body + 0] + xyz[body + 1] * xyz[body + 1] + xyz[body + 2] * xyz[body + 2] > maxDist
+                  * maxDist);
+            // divide into two 'sphere of bodies' by adjusting x 
+            if (body % 2 == 0) {
+               xyz[body + 0] += maxDist * 1.5;
+            } else {
+               xyz[body + 0] -= maxDist * 1.5;
+            }
+         }
+      }
+
+      /** 
+       * Here is the kernel entrypoint. Here is where we calculate the position of each body
+       */
+      @Override public void run() {
+         int body = getGlobalId();
+         int count = bodies * 3;
+         int globalId = body * 3;
+
+         float accx = 0.f;
+         float accy = 0.f;
+         float accz = 0.f;
+
+         float myPosx = xyz[globalId + 0];
+         float myPosy = xyz[globalId + 1];
+         float myPosz = xyz[globalId + 2];
+         for (int i = 0; i < count; i += 3) {
+            float dx = xyz[i + 0] - myPosx;
+            float dy = xyz[i + 1] - myPosy;
+            float dz = xyz[i + 2] - myPosz;
+            float invDist = rsqrt((dx * dx) + (dy * dy) + (dz * dz) + espSqr);
+            float s = mass * invDist * invDist * invDist;
+            accx = accx + s * dx;
+            accy = accy + s * dy;
+            accz = accz + s * dz;
+         }
+         accx = accx * delT;
+         accy = accy * delT;
+         accz = accz * delT;
+         xyz[globalId + 0] = myPosx + vxyz[globalId + 0] * delT + accx * .5f * delT;
+         xyz[globalId + 1] = myPosy + vxyz[globalId + 1] * delT + accy * .5f * delT;
+         xyz[globalId + 2] = myPosz + vxyz[globalId + 2] * delT + accz * .5f * delT;
+
+         vxyz[globalId + 0] = vxyz[globalId + 0] + accx;
+         vxyz[globalId + 1] = vxyz[globalId + 1] + accy;
+         vxyz[globalId + 2] = vxyz[globalId + 2] + accz;
+      }
+
+      /**
+       * Render all particles to the OpenGL context
+       * @param gl
+       */
+
+      protected void render(GL2 gl) {
+         gl.glBegin(GL2.GL_QUADS);
+
+         for (int i = 0; i < bodies * 3; i += 3) {
+            gl.glTexCoord2f(0, 1);
+            gl.glVertex3f(xyz[i + 0], xyz[i + 1] + 1, xyz[i + 2]);
+            gl.glTexCoord2f(0, 0);
+            gl.glVertex3f(xyz[i + 0], xyz[i + 1], xyz[i + 2]);
+            gl.glTexCoord2f(1, 0);
+            gl.glVertex3f(xyz[i + 0] + 1, xyz[i + 1], xyz[i + 2]);
+            gl.glTexCoord2f(1, 1);
+            gl.glVertex3f(xyz[i + 0] + 1, xyz[i + 1] + 1, xyz[i + 2]);
+         }
+         gl.glEnd();
+      }
+
+   }
+
+   public static int width;
+
+   public static int height;
+
+   public static boolean running;
+
+   public static void main(String _args[]) {
+
+      final NBodyKernel kernel = new NBodyKernel(Integer.getInteger("bodies", 8192));
+
+      JFrame frame = new JFrame("NBody");
+
+      JPanel panel = new JPanel(new BorderLayout());
+      JPanel controlPanel = new JPanel(new FlowLayout());
+      panel.add(controlPanel, BorderLayout.SOUTH);
+
+      final JButton startButton = new JButton("Start");
+
+      startButton.addActionListener(new ActionListener(){
+         @Override public void actionPerformed(ActionEvent e) {
+            running = true;
+            startButton.setEnabled(false);
+         }
+      });
+      controlPanel.add(startButton);
+      controlPanel.add(new JLabel(kernel.getExecutionMode().toString()));
+
+      controlPanel.add(new JLabel("   Particles"));
+      controlPanel.add(new JTextField("" + kernel.bodies, 5));
+
+      controlPanel.add(new JLabel("FPS"));
+      final JTextField framesPerSecondTextField = new JTextField("0", 5);
+
+      controlPanel.add(framesPerSecondTextField);
+      controlPanel.add(new JLabel("Score("));
+      JLabel miniLabel = new JLabel("<html><small>calcs</small><hr/><small>&micro;sec</small></html>");
+
+      controlPanel.add(miniLabel);
+      controlPanel.add(new JLabel(")"));
+
+      final JTextField positionUpdatesPerMicroSecondTextField = new JTextField("0", 5);
+
+      controlPanel.add(positionUpdatesPerMicroSecondTextField);
+      GLCapabilities caps = new GLCapabilities(null);
+      caps.setDoubleBuffered(true);
+      caps.setHardwareAccelerated(true);
+      final GLCanvas canvas = new GLCanvas(caps);
+      Dimension dimension = new Dimension(Integer.getInteger("width", 742), Integer.getInteger("height", 742));
+      canvas.setPreferredSize(dimension);
+
+      canvas.addGLEventListener(new GLEventListener(){
+         private double ratio;
+
+         private final float xeye = 0f;
+
+         private final float yeye = 0f;
+
+         private final float zeye = 100f;
+
+         private final float xat = 0f;
+
+         private final float yat = 0f;
+
+         private final float zat = 0f;
+
+         public final float zoomFactor = 1.0f;
+
+         private int frames;
+
+         private long last = System.currentTimeMillis();
+
+         @Override public void dispose(GLAutoDrawable drawable) {
+
+         }
+
+         @Override public void display(GLAutoDrawable drawable) {
+
+            GL2 gl = drawable.getGL().getGL2();
+
+            gl.glLoadIdentity();
+            gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+            gl.glColor3f(1f, 1f, 1f);
+
+            GLU glu = new GLU();
+            glu.gluPerspective(45f, ratio, 0f, 1000f);
+
+            glu.gluLookAt(xeye, yeye, zeye * zoomFactor, xat, yat, zat, 0f, 1f, 0f);
+            if (running) {
+               kernel.execute(kernel.bodies);
+            }
+            kernel.render(gl);
+
+            long now = System.currentTimeMillis();
+            long time = now - last;
+            frames++;
+
+            if (time > 1000) { // We update the frames/sec every second
+               if (running) {
+                  float framesPerSecond = (frames * 1000.0f) / time;
+                  int updatesPerMicroSecond = (int) ((framesPerSecond * kernel.bodies * kernel.bodies) / 1000000);
+                  framesPerSecondTextField.setText(String.format("%5.2f", framesPerSecond));
+                  positionUpdatesPerMicroSecondTextField.setText(String.format("%4d", updatesPerMicroSecond));
+               }
+               frames = 0;
+               last = now;
+            }
+            gl.glFlush();
+
+         }
+
+         @Override public void init(GLAutoDrawable drawable) {
+            final GL2 gl = drawable.getGL().getGL2();
+
+            gl.glShadeModel(GLLightingFunc.GL_SMOOTH);
+            gl.glEnable(GL.GL_BLEND);
+            gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE);
+            try {
+               InputStream textureStream = Main.class.getResourceAsStream("particle.jpg");
+               Texture texture = TextureIO.newTexture(textureStream, false, null);
+               texture.enable();
+            } catch (IOException e) {
+               e.printStackTrace();
+            } catch (GLException e) {
+               e.printStackTrace();
+            }
+
+         }
+
+         @Override public void reshape(GLAutoDrawable drawable, int x, int y, int _width, int _height) {
+            width = _width;
+            height = _height;
+
+            GL2 gl = drawable.getGL().getGL2();
+            gl.glViewport(0, 0, width, height);
+
+            ratio = (double) width / (double) height;
+
+         }
+
+      });
+
+      panel.add(canvas, BorderLayout.CENTER);
+      frame.getContentPane().add(panel, BorderLayout.CENTER);
+
+      frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+      frame.pack();
+      frame.setVisible(true);
+
+      FPSAnimator animator = new FPSAnimator(canvas, 200);
+      animator.start();
+
+   }
+
+}
diff --git a/examples/nbody/src/com/amd/aparapi/examples/nbody/particle.jpg b/examples/nbody/src/com/amd/aparapi/examples/nbody/particle.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..70e28ac5ea0a5ae58736f61f46ef5a326fbfbde0
GIT binary patch
literal 1056
zcmex=<NpH&0WUXCHwH#VMg|WcWcYuZ!5PG(2!ITs$N-S${|6WZIT#ce6qp&67?=bZ
znFSgDA7PMZU|?j0n9TqMj7-cdtZeKYoLt;M1zQCem>8LvnOK-vSy@<ss%wGr3@n1I
zLW+itY{G$w>`H|qMvW5}awt1(JSZA;@q>zSQc)8pmzcPOq?D?fx`w8fiK&^ng{76V
zi>sTvho@I?NN8AiL}XNQN@`kqMrKxVNoiSmMP*fUOKV$uM`zch$y26In?7UatVN5L
zEM2yI#mZHiHgDOwZTpU$yAB;ba`f2o6DLnyx_ss8wd*%--g@}x@sp>|p1*kc>f@)+
zU%r0({^RE_kiQrinBhSN@fe!F1cClyVqsxsVF&q(k*OSrnFU!`6%E;h90S=C3x$=8
z8aYIqCNA7~kW<+>=!0ld(M2vX6_bamA3<IN`;0h`HId~rxW^Fwy2Zf5%m|D;W<dsf
zhJRuv{Cu8e50jnT-W{0txbbJtuj<nEbr<XeUr9~T`1Y;XcQ?!1-aa;~0>cBZY;CjZ
zTk7Py1Fqye%xyn2%T)1zLR;dG@9%2;FaP@apP?zP{-B=8`dh{BnJR7fZYpi{d^RuQ
zU@v3La}}P+FaJp@$R9u6VJCb)bE2opw@I$s)t~iFdA{LE)$b=s`|3XOHL9*YF-b9g
zc0<(!`x7U>{mK5V1~hZUe};n=U*6wrd-vMUWm}?*ua5Deb=P8qROEKPvEuuw&ivEu
z$Kpjt6DuoLaT|F(5bitUX8-H{`W5V+A0{8UR^|J5>1nOqt|qx#``khs&o5stQ~Kmn
z_OBg4lZ)yPhOetnTWe&Yo0qHHx}Z-o_kKb+V`00@bB5;^%3jAGJ=Xe2d`qH=U*VqQ
zIq9;W?B?3b{jj^c=uhC@jXg@SUM<NC)=U*o<`uuay#KL-{N?q3M6Uni@-%;IT3K0N
zT+Y*LlPi<e!=;qWWWadn@%GQ>MgQ#o<9j`M|L$EjOrJKM$b0hqdSl;L{SG_zd#?&N
roh;Ou-R@SVA~-)j=JVvf=gjNdvUk0{D=Fu$^6p)&bzSTW=KnVVV0)Pr

literal 0
HcmV?d00001

diff --git a/samples/blackscholes/blackscholes.bash b/samples/blackscholes/blackscholes.bash
new file mode 100644
index 00000000..f45b682a
--- /dev/null
+++ b/samples/blackscholes/blackscholes.bash
@@ -0,0 +1,7 @@
+java \
+   -Djava.library.path=..\..\com.amd.aparapi.jni \
+   -Dcom.amd.aparapi.executionMode=$1 \
+   -Dsize=$2  \
+   -Diterations=$3 \
+   -classpath blackscholes.jar:..\..\com.amd.aparapi\aparapi.jar \
+   com.amd.aparapi.samples.blackscholes.Main 
diff --git a/samples/blackscholes/blackscholes.bat b/samples/blackscholes/blackscholes.bat
new file mode 100644
index 00000000..d1139bb0
--- /dev/null
+++ b/samples/blackscholes/blackscholes.bat
@@ -0,0 +1,7 @@
+java ^
+   -Djava.library.path=..\..\com.amd.aparapi.jni ^
+   -Dcom.amd.aparapi.executionMode=%1 ^
+   -Dsize=%2 ^
+   -Diterations=%3 ^
+   -classpath blackscholes.jar;..\..\com.amd.aparapi\aparapi.jar ^
+   com.amd.aparapi.samples.blackscholes.Main 
diff --git a/samples/blackscholes/build.xml b/samples/blackscholes/build.xml
new file mode 100644
index 00000000..4b368168
--- /dev/null
+++ b/samples/blackscholes/build.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+
+<project name="blackscholes" default="build" basedir=".">
+
+   <target name="build" depends="clean">
+      <mkdir dir="classes"/>
+      <javac srcdir="src" destdir="classes" debug="on" includeantruntime="false" >
+         <classpath>
+            <pathelement path="../../com.amd.aparapi/aparapi.jar"/>
+         </classpath>
+      </javac>
+      <jar jarfile="${ant.project.name}.jar" basedir="classes"/>
+   </target>
+
+   <target name="clean">
+      <delete dir="classes"/>
+      <delete file="${ant.project.name}.jar"/>
+   </target>
+
+</project>
diff --git a/samples/blackscholes/src/com/amd/aparapi/samples/blackscholes/Main.java b/samples/blackscholes/src/com/amd/aparapi/samples/blackscholes/Main.java
new file mode 100644
index 00000000..a80ddd65
--- /dev/null
+++ b/samples/blackscholes/src/com/amd/aparapi/samples/blackscholes/Main.java
@@ -0,0 +1,203 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi.samples.blackscholes;
+
+import com.amd.aparapi.Kernel;
+
+public class Main{
+
+   public static class BlackScholesKernel extends Kernel{
+
+      /*
+      * For a description of the algorithm and the terms used, please see the
+      * documentation for this sample.
+      *
+      * On invocation of kernel blackScholes, each work thread calculates call price
+      * and put price values for given stock price, option strike price, 
+      * time to expiration date, risk free interest and volatility factor.
+      */
+
+      final float S_LOWER_LIMIT = 10.0f;
+
+      final float S_UPPER_LIMIT = 100.0f;
+
+      final float K_LOWER_LIMIT = 10.0f;
+
+      final float K_UPPER_LIMIT = 100.0f;
+
+      final float T_LOWER_LIMIT = 1.0f;
+
+      final float T_UPPER_LIMIT = 10.0f;
+
+      final float R_LOWER_LIMIT = 0.01f;
+
+      final float R_UPPER_LIMIT = 0.05f;
+
+      final float SIGMA_LOWER_LIMIT = 0.01f;
+
+      final float SIGMA_UPPER_LIMIT = 0.10f;
+
+      /**
+      * @brief   Abromowitz Stegun approxmimation for PHI (Cumulative Normal Distribution Function)
+      * @param   X input value
+      * @param   phi pointer to store calculated CND of X
+      */
+      float phi(float X) {
+         final float c1 = 0.319381530f;
+         final float c2 = -0.356563782f;
+         final float c3 = 1.781477937f;
+         final float c4 = -1.821255978f;
+         final float c5 = 1.330274429f;
+
+         final float zero = 0.0f;
+         final float one = 1.0f;
+         final float two = 2.0f;
+         final float temp4 = 0.2316419f;
+
+         final float oneBySqrt2pi = 0.398942280f;
+
+         float absX = abs(X);
+         float t = one / (one + temp4 * absX);
+
+         float y = one - oneBySqrt2pi * exp(-X * X / two) * t * (c1 + t * (c2 + t * (c3 + t * (c4 + t * c5))));
+
+         float result = (X < zero) ? (one - y) : y;
+
+         return result;
+      }
+
+      /*
+      * @brief   Calculates the call and put prices by using Black Scholes model
+      * @param   s       Array of random values of current option price
+      * @param   sigma   Array of random values sigma
+      * @param   k       Array of random values strike price
+      * @param   t       Array of random values of expiration time
+      * @param   r       Array of random values of risk free interest rate
+      * @param   width   Width of call price or put price array
+      * @param   call    Array of calculated call price values
+      * @param   put     Array of calculated put price values
+      */
+      @Override public void run() {
+         float d1, d2;
+         float phiD1, phiD2;
+         float sigmaSqrtT;
+         float KexpMinusRT;
+
+         int gid = getGlobalId();
+         float two = 2.0f;
+         float inRand = randArray[gid];
+         float S = S_LOWER_LIMIT * inRand + S_UPPER_LIMIT * (1.0f - inRand);
+         float K = K_LOWER_LIMIT * inRand + K_UPPER_LIMIT * (1.0f - inRand);
+         float T = T_LOWER_LIMIT * inRand + T_UPPER_LIMIT * (1.0f - inRand);
+         float R = R_LOWER_LIMIT * inRand + R_UPPER_LIMIT * (1.0f - inRand);
+         float sigmaVal = SIGMA_LOWER_LIMIT * inRand + SIGMA_UPPER_LIMIT * (1.0f - inRand);
+
+         sigmaSqrtT = sigmaVal * sqrt(T);
+
+         d1 = (log(S / K) + (R + sigmaVal * sigmaVal / two) * T) / sigmaSqrtT;
+         d2 = d1 - sigmaSqrtT;
+
+         KexpMinusRT = K * exp(-R * T);
+
+         phiD1 = phi(d1);
+         phiD2 = phi(d2);
+
+         call[gid] = S * phiD1 - KexpMinusRT * phiD2;
+
+         phiD1 = phi(-d1);
+         phiD2 = phi(-d2);
+
+         put[gid] = KexpMinusRT * phiD2 - S * phiD1;
+      }
+
+      private float randArray[];
+
+      private float put[];
+
+      private float call[];
+
+      public BlackScholesKernel(int size) {
+         randArray = new float[size];
+         call = new float[size];
+         put = new float[size];
+
+         for (int i = 0; i < size; i++) {
+            randArray[i] = i * 1.0f / size;
+         }
+      }
+
+      public void showArray(float ary[], String name, int count) {
+         String line;
+         line = name + ": ";
+         for (int i = 0; i < count; i++) {
+            if (i > 0)
+               line += ", ";
+            line += ary[i];
+         }
+         System.out.println(line);
+      }
+
+      public void showResults(int count) {
+         showArray(call, "Call Prices", count);
+         showArray(put, "Put  Prices", count);
+      }
+   }
+
+   public static void main(String[] _args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+
+      int size = Integer.getInteger("size", 512);
+      int iterations = Integer.getInteger("iterations", 5); 
+      System.out.println("size ="+size);
+      System.out.println("iterations ="+iterations);
+      BlackScholesKernel kernel = new BlackScholesKernel(size);
+
+      long totalExecTime = 0;
+      long iterExecTime = 0;
+      /*
+      for (int i = 0; i < iterations; i++) {
+         iterExecTime = kernel.execute(size).getExecutionTime();
+         totalExecTime += iterExecTime;
+      }*/
+      kernel.execute(size, iterations);
+      System.out.println("Average execution time " + kernel.getAccumulatedExecutionTime() / iterations);
+      kernel.showResults(10);
+
+      kernel.dispose();
+   }
+
+}
diff --git a/samples/mandel/.classpath b/samples/mandel/.classpath
new file mode 100644
index 00000000..2b3d4294
--- /dev/null
+++ b/samples/mandel/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.amd.aparapi"/>
+	<classpathentry kind="output" path="classes"/>
+</classpath>
diff --git a/samples/mandel/.project b/samples/mandel/.project
new file mode 100644
index 00000000..6be9bbf8
--- /dev/null
+++ b/samples/mandel/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>mandel</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/samples/mandel/build.xml b/samples/mandel/build.xml
new file mode 100644
index 00000000..32878ce6
--- /dev/null
+++ b/samples/mandel/build.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+
+<project name="mandel" default="build" basedir=".">
+   <target name="build" depends="clean">
+      <mkdir dir="classes"/>
+      <javac srcdir="src" destdir="classes" debug="on" includeantruntime="false" >
+         <classpath>
+            <pathelement path="../../com.amd.aparapi/aparapi.jar"/>
+         </classpath>
+      </javac>
+      <jar jarfile="${ant.project.name}.jar" basedir="classes"/>
+   </target>
+
+   <target name="clean">
+      <delete dir="classes"/>
+      <delete file="${ant.project.name}.jar"/>
+   </target>
+
+
+</project>
diff --git a/samples/mandel/mandel.bat b/samples/mandel/mandel.bat
new file mode 100644
index 00000000..61ae2889
--- /dev/null
+++ b/samples/mandel/mandel.bat
@@ -0,0 +1,9 @@
+
+set PATH=%PATH%;C:\Program Files\AMD APP\bin\x86
+%JAVA_HOME%/bin/java ^
+ -Djava.library.path=../../com.amd.aparapi.jni ^
+ -Dcom.amd.aparapi.executionMode=%1 ^
+ -classpath ../../com.amd.aparapi/aparapi.jar;mandel.jar ^
+ com.amd.aparapi.sample.mandel.Main
+
+
diff --git a/samples/mandel/mandel.sh b/samples/mandel/mandel.sh
new file mode 100644
index 00000000..5d9f9a7c
--- /dev/null
+++ b/samples/mandel/mandel.sh
@@ -0,0 +1,5 @@
+${JAVA_HOME}/bin/java\
+ -Djava.library.path=../../com.amd.aparapi.jni\
+ -Dcom.amd.aparapi.executionMode=$1\
+ -classpath ../../com.amd.aparapi/aparapi.jar:mandel.jar\
+ com.amd.aparapi.sample.mandel.Main
diff --git a/samples/mandel/src/com/amd/aparapi/sample/mandel/Main.java b/samples/mandel/src/com/amd/aparapi/sample/mandel/Main.java
new file mode 100644
index 00000000..5879f785
--- /dev/null
+++ b/samples/mandel/src/com/amd/aparapi/sample/mandel/Main.java
@@ -0,0 +1,285 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+
+package com.amd.aparapi.sample.mandel;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBufferInt;
+
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+
+import com.amd.aparapi.Kernel;
+
+/**
+ * An example Aparapi application which displays a view of the Mandelbrot set and lets the user zoom in to a particular point. 
+ * 
+ * When the user clicks on the view, this example application will zoom in to the clicked point and zoom out there after.
+ * On GPU, additional computing units will offer a better viewing experience. On the other hand on CPU, this example 
+ * application might suffer with sub-optimal frame refresh rate as compared to GPU. 
+ *  
+ * @author gfrost
+ *
+ */
+
+public class Main{
+
+   /**
+    * An Aparapi Kernel implementation for creating a scaled view of the mandelbrot set.
+    *  
+    * @author gfrost
+    *
+    */
+
+   public static class MandelKernel extends Kernel{
+
+      /** RGB buffer used to store the Mandelbrot image. This buffer holds (width * height) RGB values. */
+      final private int rgb[];
+
+      /** Mandelbrot image width. */
+      final private int width;
+
+      /** Mandelbrot image height. */
+      final private int height;
+
+      /** Palette used for each iteration value 0..maxIterations. */
+      final private int pallette[];
+
+      /** Maximum iterations we will check for. */
+      final private int maxIterations;
+
+      /** Mutable values of scale, offsetx and offsety so that we can modify the zoom level and position of a view. */
+      private float scale = .0f;
+
+      private float offsetx = .0f;
+
+      private float offsety = .0f;
+
+      /**
+       * Initialize the Kernel.
+       *  
+       * @param _width Mandelbrot image width
+       * @param _height Mandelbrot image height
+       * @param _rgb Mandelbrot image RGB buffer
+       * @param _pallette Mandelbrot image palette
+       */
+      public MandelKernel(int _width, int _height, int[] _rgb, int[] _pallette) {
+         width = _width;
+         height = _height;
+         rgb = _rgb;
+         pallette = _pallette;
+         maxIterations = pallette.length - 1;
+
+      }
+
+      @Override public void run() {
+
+         /** Determine which RGB value we are going to process (0..RGB.length). */
+         int gid = getGlobalId();
+
+         /** Translate the gid into an x an y value. */
+         float x = (((gid % width * scale) - ((scale / 2) * width)) / width) + offsetx;
+
+         float y = (((gid / height * scale) - ((scale / 2) * height)) / height) + offsety;
+
+         int count = 0;
+
+         float zx = x;
+         float zy = y;
+         float new_zx = 0f;
+
+         // Iterate until the algorithm converges or until maxIterations are reached.
+         while (count < maxIterations && zx * zx + zy * zy < 8) {
+            new_zx = zx * zx - zy * zy + x;
+            zy = 2 * zx * zy + y;
+            zx = new_zx;
+            count++;
+         }
+
+         // Pull the value out of the palette for this iteration count.
+         rgb[gid] = pallette[count];
+      }
+
+      public void setScaleAndOffset(float _scale, float _offsetx, float _offsety) {
+         offsetx = _offsetx;
+         offsety = _offsety;
+         scale = _scale;
+      }
+
+   }
+
+   /** User selected zoom-in point on the Mandelbrot view. */
+   public static volatile Point to = null;
+
+   @SuppressWarnings("serial") public static void main(String[] _args) {
+
+      JFrame frame = new JFrame("MandelBrot");
+
+      /** Width of Mandelbrot view. */
+      final int width = 768;
+
+      /** Height of Mandelbrot view. */
+      final int height = 768;
+
+      /** Maximum iterations for Mandelbrot. */
+      final int maxIterations = 256;
+
+      /** Palette which maps iteration values to RGB values. */
+      final int pallette[] = new int[maxIterations + 1];
+
+      //Initialize palette values
+      for (int i = 0; i < maxIterations; i++) {
+         float h = i / (float) maxIterations;
+         float b = 1.0f - h * h;
+         pallette[i] = Color.HSBtoRGB(h, 1f, b);
+      }
+
+      /** Image for Mandelbrot view. */
+      final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+      final BufferedImage offscreen = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+      // Draw Mandelbrot image
+      JComponent viewer = new JComponent(){
+         @Override public void paintComponent(Graphics g) {
+
+            g.drawImage(image, 0, 0, width, height, this);
+         }
+      };
+
+      // Set the size of JComponent which displays Mandelbrot image
+      viewer.setPreferredSize(new Dimension(width, height));
+
+      final Object doorBell = new Object();
+
+      // Mouse listener which reads the user clicked zoom-in point on the Mandelbrot view 
+      viewer.addMouseListener(new MouseAdapter(){
+         @Override public void mouseClicked(MouseEvent e) {
+            to = e.getPoint();
+            synchronized (doorBell) {
+               doorBell.notify();
+            }
+         }
+      });
+
+      // Swing housework to create the frame
+      frame.getContentPane().add(viewer);
+      frame.pack();
+      frame.setLocationRelativeTo(null);
+      frame.setVisible(true);
+
+      // Extract the underlying RGB buffer from the image.
+      // Pass this to the kernel so it operates directly on the RGB buffer of the image
+      final int[] rgb = ((DataBufferInt) offscreen.getRaster().getDataBuffer()).getData();
+      final int[] imageRgb = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
+      // Create a Kernel passing the size, RGB buffer and the palette.
+      final MandelKernel kernel = new MandelKernel(width, height, rgb, pallette);
+
+      float defaultScale = 3f;
+
+      // Set the default scale and offset, execute the kernel and force a repaint of the viewer.
+      kernel.setScaleAndOffset(defaultScale, -1f, 0f);
+      kernel.execute(width * height);
+      System.arraycopy(rgb, 0, imageRgb, 0, rgb.length);
+      viewer.repaint();
+
+      // Report target execution mode: GPU or JTP (Java Thread Pool).
+      System.out.println("Execution mode=" + kernel.getExecutionMode());
+
+      // Window listener to dispose Kernel resources on user exit.
+      frame.addWindowListener(new WindowAdapter(){
+         public void windowClosing(WindowEvent _windowEvent) {
+            kernel.dispose();
+            System.exit(0);
+         }
+      });
+
+      // Wait until the user selects a zoom-in point on the Mandelbrot view.
+      while (true) {
+
+         // Wait for the user to click somewhere
+         while (to == null) {
+            synchronized (doorBell) {
+               try {
+                  doorBell.wait();
+               } catch (InterruptedException ie) {
+                  ie.getStackTrace();
+               }
+            }
+         }
+
+         float x = -1f;
+         float y = 0f;
+         float scale = defaultScale;
+         float tox = (float) (to.x - width / 2) / width * scale;
+         float toy = (float) (to.y - height / 2) / height * scale;
+
+         // This is how many frames we will display as we zoom in and out.
+         int frames = 128;
+         long startMillis = System.currentTimeMillis();
+         for (int sign = -1; sign < 2; sign += 2) {
+            for (int i = 0; i < frames - 4; i++) {
+               scale = scale + sign * defaultScale / frames;
+               x = x - sign * (tox / frames);
+               y = y - sign * (toy / frames);
+
+               // Set the scale and offset, execute the kernel and force a repaint of the viewer.
+               kernel.setScaleAndOffset(scale, x, y);
+               kernel.execute(width * height);
+               System.arraycopy(rgb, 0, imageRgb, 0, rgb.length);
+               viewer.repaint();
+            }
+         }
+
+         long elapsedMillis = System.currentTimeMillis() - startMillis;
+         System.out.println("FPS = " + frames * 1000 / elapsedMillis);
+
+         // Reset zoom-in point.
+         to = null;
+
+      }
+
+   }
+
+}
diff --git a/samples/squares/.classpath b/samples/squares/.classpath
new file mode 100644
index 00000000..2b3d4294
--- /dev/null
+++ b/samples/squares/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.amd.aparapi"/>
+	<classpathentry kind="output" path="classes"/>
+</classpath>
diff --git a/samples/squares/.project b/samples/squares/.project
new file mode 100644
index 00000000..af343471
--- /dev/null
+++ b/samples/squares/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>squares</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/samples/squares/build.xml b/samples/squares/build.xml
new file mode 100644
index 00000000..291ebc9d
--- /dev/null
+++ b/samples/squares/build.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+
+<project name="squares" default="build" basedir=".">
+   <target name="build" depends="clean">
+      <mkdir dir="classes"/>
+      <javac srcdir="src" destdir="classes" debug="on" includeantruntime="false" >
+         <classpath>
+            <pathelement path="../../com.amd.aparapi/aparapi.jar"/>
+         </classpath>
+      </javac>
+      <jar jarfile="${ant.project.name}.jar" basedir="classes"/>
+   </target>
+
+   <target name="clean">
+      <delete dir="classes"/>
+      <delete file="${ant.project.name}.jar"/>
+   </target>
+
+
+</project>
diff --git a/samples/squares/squares.bat b/samples/squares/squares.bat
new file mode 100644
index 00000000..a47a94e1
--- /dev/null
+++ b/samples/squares/squares.bat
@@ -0,0 +1,6 @@
+%JAVA_HOME%/bin/java ^
+ -Djava.library.path=../../com.amd.aparapi.jni ^
+ -Dcom.amd.aparapi.executionMode=%1 ^
+ -classpath ../../com.amd.aparapi/aparapi.jar;squares.jar ^
+ com.amd.aparapi.sample.squares.Main
+
diff --git a/samples/squares/squares.sh b/samples/squares/squares.sh
new file mode 100644
index 00000000..81dde65f
--- /dev/null
+++ b/samples/squares/squares.sh
@@ -0,0 +1,5 @@
+${JAVA_HOME}/bin/java \
+ -Djava.library.path=../../com.amd.aparapi.jni \
+ -Dcom.amd.aparapi.executionMode=%1 \
+ -classpath ../../com.amd.aparapi/aparapi.jar:squares.jar \
+ com.amd.aparapi.sample.squares.Main
diff --git a/samples/squares/src/com/amd/aparapi/sample/squares/Main.java b/samples/squares/src/com/amd/aparapi/sample/squares/Main.java
new file mode 100644
index 00000000..929d02b3
--- /dev/null
+++ b/samples/squares/src/com/amd/aparapi/sample/squares/Main.java
@@ -0,0 +1,94 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+
+package com.amd.aparapi.sample.squares;
+
+import com.amd.aparapi.Kernel;
+
+/**
+ * An example Aparapi application which computes and displays squares of a set of 512 input values.
+ * While executing on GPU using Aparpi framework, each square value is computed in a separate kernel invocation and 
+ * can thus maximize performance by optimally utilizing all GPU computing units 
+ *  
+ * @author gfrost
+ *
+ */
+
+public class Main{
+
+   public static void main(String[] _args) {
+
+      final int size = 512;
+
+      /** Input float array for which square values need to be computed. */
+      final float[] values = new float[size];
+
+      /** Initialize input array. */
+      for (int i = 0; i < size; i++) {
+         values[i] = i;
+      }
+
+      /** Output array which will be populated with square values of corresponding input array elements. */
+      final float[] squares = new float[size];
+
+      /** Aparapi Kernel which computes squares of input array elements and populates them in corresponding elements of 
+       * output array. 
+       **/
+      Kernel kernel = new Kernel(){
+         @Override public void run() {
+            int gid = getGlobalId();
+            squares[gid] = values[gid] * values[gid];
+         }
+      };
+
+      // Execute Kernel.
+      kernel.execute(512);
+
+      // Report target execution mode: GPU or JTP (Java Thread Pool).
+      System.out.println("Execution mode=" + kernel.getExecutionMode());
+
+      // Display computed square values.
+      for (int i = 0; i < size; i++) {
+         System.out.printf("%6.0f %8.0f\n", values[i], squares[i]);
+      }
+
+      // Dispose Kernel resources.
+      kernel.dispose();
+   }
+
+}
diff --git a/test/codegen/.classpath b/test/codegen/.classpath
new file mode 100644
index 00000000..04de8d49
--- /dev/null
+++ b/test/codegen/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src/java"/>
+	<classpathentry kind="src" path="src/genjava"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/com.amd.aparapi"/>
+	<classpathentry kind="output" path="classes"/>
+</classpath>
diff --git a/test/codegen/.project b/test/codegen/.project
new file mode 100644
index 00000000..971890c3
--- /dev/null
+++ b/test/codegen/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>codegen</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/test/codegen/build.xml b/test/codegen/build.xml
new file mode 100644
index 00000000..1118e3da
--- /dev/null
+++ b/test/codegen/build.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+
+<project name="codegen" default="junit" basedir=".">
+
+   <!--<property name="junit.jar" value="/home/gfrost/aparapi/trunk/tools/junit/junit.jar"/>-->
+   <property name="junit.jar" value="C:\Users\gfrost\javalabs\projects\aparapi\trunk\tools\junit\junit.jar"/>
+
+   <path id="classpath">
+      <pathelement path="..\..\com.amd.aparapi\aparapi.jar"/>
+      <pathelement path="${junit.jar}"/>
+      <pathelement path="classes"/>
+   </path>
+
+   <target name="check">
+      <fail message="Error:">
+         <condition>
+            <not><isset property="junit.jar"/></not>
+         </condition>
+         <![CDATA[
+         You will need to edit test/codegen/build.xml
+
+         At present junit.dir is not set.  It needs to point to the junit jar file in your junit installation.
+
+         You can install/download junit from www.junit.org.
+         ]]>
+      </fail>
+      <available file="${junit.jar}" type="file" property="junit.jar.exists"/>
+      <fail message="Error:">
+         <condition>
+            <not><isset property="junit.jar.exists"/></not>
+         </condition>
+         <![CDATA[
+         You will need to edit test/codegen/build.xml
+
+         At present junit.jar is set to ${junit.jar} but that file does not exist
+         ]]>
+      </fail>
+   </target>
+
+   <target name="clean">
+      <delete dir="classes"/>
+      <delete dir="junit"/>
+      <delete dir="src/genjava/com"/>
+   </target>
+
+   <target name="junit" depends="clean, check">
+      <mkdir dir="classes"/>
+      <javac srcdir="src/java" destdir="classes" debug="on"  includeAntRuntime="false" classpathref="classpath" />
+
+      <java classname="com.amd.aparapi.CreateJUnitTests" classpathref="classpath">
+         <sysproperty key="root" value="${basedir}"/>
+      </java>
+
+      <javac srcdir="src/genjava" destdir="classes" debug="on"  includeAntRuntime="false"  classpathref="classpath"/>
+
+      <mkdir dir="junit"/>
+      <mkdir dir="junit/data"/>
+      <junit printsummary="false" fork="false" haltonfailure="false" failureproperty="tests.failed" showoutput="false">
+         <formatter type="xml" />
+         <classpath refid="classpath"/>
+         <batchtest todir="junit/data">
+            <fileset dir="src/genjava"/> 
+         </batchtest>
+      </junit>
+
+      <junitreport todir="junit/data">
+         <fileset dir="junit/data"/>
+         <report format="frames" todir="junit/html" />
+      </junitreport>
+   </target>
+
+</project>
diff --git a/test/codegen/src/java/com/amd/aparapi/CodeGenJUnitBase.java b/test/codegen/src/java/com/amd/aparapi/CodeGenJUnitBase.java
new file mode 100644
index 00000000..6631510b
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/CodeGenJUnitBase.java
@@ -0,0 +1,110 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import static org.junit.Assert.assertTrue;
+
+public class CodeGenJUnitBase{
+
+   protected void test(Class<?> _class, Class<? extends AparapiException> _expectedExceptionType, String[] expectedOpenCL) {
+      try {
+         // Source source = new Source(_class, new File("src/java"));
+         // System.out.println("opencl\n"+source.getOpenCL());
+
+         //  String expected = source.getOpenCLString();
+
+         ClassModel classModel = new ClassModel(_class);
+
+         // construct an artficial instance of our class here
+         // we assume the specified class will have a null constructor
+         Object kernelInstance = _class.getConstructor((Class<?>[]) null).newInstance();
+
+         Entrypoint entrypoint = classModel.getEntrypoint("run", kernelInstance instanceof Kernel ? kernelInstance : null);
+         String actual = KernelWriter.writeToString(entrypoint);
+
+         if (_expectedExceptionType == null) {
+            int matched = 0;
+            for (String expected : expectedOpenCL) {
+               if (Diff.same(actual, expected)) {
+                  break;
+               }
+               matched++;
+            }
+            boolean same = (matched < expectedOpenCL.length);
+
+            if (!same) {
+               System.out.println("---" + _class.getName()
+                     + "------------------------------------------------------------------------------");
+               boolean first = true;
+               for (String expected : expectedOpenCL) {
+                  if (first) {
+                     first = false;
+                  } else {
+                     System.out.println("}");
+                  }
+                  System.out.println("Expected {\n" + expected);
+               }
+               System.out.println("}Actual\n{" + actual);
+               System.out
+                     .println("}\n------------------------------------------------------------------------------------------------------");
+
+            } else {
+               System.out.println("Matched{" + actual);
+               System.out
+                     .println("}\n------------------------------------------------------------------------------------------------------");
+
+            }
+            assertTrue(_class.getSimpleName(), same);
+         } else {
+            assertTrue("Expected exception " + _expectedExceptionType, false);
+         }
+
+      } catch (Throwable t) {
+         if (_expectedExceptionType == null || !t.getClass().isAssignableFrom(_expectedExceptionType)) {
+            t.printStackTrace();
+            assertTrue("Unexpected exception " + t, false);
+         }
+      }
+   }
+
+   protected void test(Class<?> _class, String[] expectedOpenCL) {
+      test(_class, null, expectedOpenCL);
+
+   }
+
+}
diff --git a/test/codegen/src/java/com/amd/aparapi/CreateJUnitTests.java b/test/codegen/src/java/com/amd/aparapi/CreateJUnitTests.java
new file mode 100644
index 00000000..58a02788
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/CreateJUnitTests.java
@@ -0,0 +1,127 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public class CreateJUnitTests{
+   public static void main(String[] args) throws ClassNotFoundException, FileNotFoundException, IOException {
+      File rootDir = new File(System.getProperty("root", "."));
+
+      String rootPackageName = CreateJUnitTests.class.getPackage().getName();
+      String testPackageName = rootPackageName + ".test";
+      File sourceDir = new File(rootDir, "src/java");
+      System.out.println(sourceDir.getCanonicalPath());
+      File testDir = new File(sourceDir, testPackageName.replace(".", "/"));
+      System.out.println(testDir.getCanonicalPath());
+
+      List<String> classNames = new ArrayList<String>();
+      for (File sourceFile : testDir.listFiles(new FilenameFilter(){
+
+         @Override public boolean accept(File dir, String name) {
+            return (name.endsWith(".java"));
+         }
+      })) {
+         String fileName = sourceFile.getName();
+         String className = fileName.substring(0, fileName.length() - ".java".length());
+         classNames.add(className);
+      }
+
+      File genSourceDir = new File(rootDir, "src/genjava");
+      File codeGenDir = new File(genSourceDir, rootPackageName.replace(".", "/") + "/test/junit/codegen/");
+      codeGenDir.mkdirs();
+
+      for (String className : classNames) {
+
+         Source source = new Source(Class.forName(testPackageName + "." + className), sourceDir);
+
+         StringBuilder sb = new StringBuilder();
+         sb.append("package com.amd.aparapi.test.junit.codegen;\n");
+         sb.append("import org.junit.Test;\n");
+         String doc = source.getDocString();
+         if (doc.length() > 0) {
+            sb.append("/**\n");
+            sb.append(doc);
+            sb.append("\n */\n");
+         }
+         sb.append("public class " + className + " extends com.amd.aparapi.CodeGenJUnitBase{\n");
+         sb.append("   @Test public void " + className + "(){\n");
+         if (source.getOpenCLSectionCount() > 0) {
+
+            sb.append("   String[] expectedOpenCL = new String[]{\n");
+            for (List<String> opencl : source.getOpenCL()) {
+               sb.append("   \"\"\n");
+               for (String line : opencl) {
+                  sb.append("   +\"" + line + "\\n\"\n");
+               }
+               sb.append("   ,\n");
+            }
+            sb.append("   };\n");
+         } else {
+            sb.append("   String[] expectedOpenCL = null;\n");
+         }
+
+         String exceptions = source.getExceptionsString();
+         if (exceptions.length() > 0) {
+            sb.append("   Class<? extends com.amd.aparapi.AparapiException> expectedException = ");
+
+            sb.append("com.amd.aparapi." + exceptions + ".class");
+            sb.append(";\n");
+         } else {
+            sb.append("   Class<? extends com.amd.aparapi.AparapiException> expectedException = null;\n");
+         }
+         sb.append("       test(" + testPackageName + "." + className + ".class, expectedException, expectedOpenCL);\n");
+         sb.append("   }\n");
+         sb.append("}\n");
+         //  System.out.println(sb.toString());
+
+         File generatedFile = new File(codeGenDir, className + ".java");
+         PrintStream out = new PrintStream(generatedFile);
+         out.append(sb.toString());
+         out.close();
+
+      }
+
+   }
+}
diff --git a/test/codegen/src/java/com/amd/aparapi/Diff.java b/test/codegen/src/java/com/amd/aparapi/Diff.java
new file mode 100644
index 00000000..be197442
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/Diff.java
@@ -0,0 +1,267 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.awt.Point;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Diff{
+
+   static int[] hash(String[] lines) {
+      int[] val = new int[lines.length];
+      for (int i = 0; i < lines.length; i++) {
+         val[i] = lines[i].hashCode();
+      }
+      return (val);
+   }
+
+   static void costDiag(List<Point>[][] flags, int x, int y) {
+      if (x == 0 || y == 0 || flags[x - 1][y - 1] == null) {
+         if (x < (flags.length - 2) && y < (flags[0].length - 2)) {
+            flags[x][y] = new ArrayList<Point>();
+            flags[x][y].add(new Point(x, y));
+         }
+      } else {
+         flags[x - 1][y - 1].add(new Point(x, y));
+         flags[x][y] = flags[x - 1][y - 1];
+      }
+   }
+
+   static void cleanIslands(List<Point>[][] flags, int x, int y) {
+      flags[x][y] = null;
+      if (x > 0 && y > 0 && flags[x - 1][y - 1] != null && flags[x - 1][y - 1].size() == 1) {
+         flags[x - 1][y - 1] = null;
+      }
+   }
+
+   public static class DiffResult{
+
+      public static enum TYPE {
+         SAME,
+         LEFT,
+         RIGHT
+      };
+
+      public static class Block{
+         int lhsFrom;
+
+         int rhsFrom;
+
+         int lhsTo;
+
+         int rhsTo;
+
+         TYPE type;
+
+         public Block(TYPE _type, int _lhsFrom, int _rhsFrom) {
+            lhsFrom = lhsTo = _lhsFrom;
+            rhsFrom = rhsTo = _rhsFrom;
+            type = _type;
+         }
+
+         public void extend(int _lhsTo, int _rhsTo) {
+            lhsTo = _lhsTo;
+            rhsTo = _rhsTo;
+         }
+
+         public String toString(String[] _lhs, String[] _rhs) {
+            StringBuilder sb = new StringBuilder();
+            sb.append(type).append("\n");
+
+            switch (type) {
+               case SAME:
+                  for (int i = lhsFrom; i <= lhsTo; i++) {
+                     sb.append("  ==" + _lhs[i]).append("\n");
+                  }
+                  break;
+               case LEFT:
+                  for (int i = lhsFrom; i <= lhsTo; i++) {
+                     sb.append("  <" + _lhs[i]).append("\n");
+                  }
+                  break;
+               case RIGHT:
+                  for (int i = rhsFrom; i <= rhsTo; i++) {
+                     sb.append("  >" + _rhs[i]).append("\n");
+                  }
+                  break;
+            }
+            return (sb.toString());
+         }
+
+      }
+
+      List<Block> blocks = new ArrayList<Block>();
+
+      private String[] rhs;
+
+      private String[] lhs;
+
+      public void add(TYPE _type, int lhs, int rhs) {
+         if (false) {
+            if (blocks.size() > 0) {
+               Block lastBlock = blocks.get(blocks.size() - 1);
+               if (lastBlock.type == _type) {
+                  lastBlock.extend(lhs, rhs);
+               } else {
+                  blocks.add(new Block(_type, lhs, rhs));
+               }
+            } else {
+               blocks.add(new Block(_type, lhs, rhs));
+            }
+         }
+         blocks.add(new Block(_type, lhs, rhs));
+      }
+
+      DiffResult(String[] _lhs, String[] _rhs) {
+         lhs = _lhs;
+         rhs = _rhs;
+      }
+
+      public String[] getLhs() {
+         return lhs;
+      }
+
+      public String[] getRhs() {
+         return rhs;
+      }
+
+      public String toString() {
+         StringBuilder sb = new StringBuilder();
+         for (Block block : blocks) {
+            sb.append(block.toString(lhs, rhs)).append("\n");
+         }
+         return (sb.toString());
+      }
+   }
+
+   @SuppressWarnings("unchecked") public static DiffResult diff(String[] lhsString, String[] rhsString) {
+      DiffResult diffResult = new DiffResult(lhsString, rhsString);
+      int[] lhsHash = hash(lhsString);
+      int[] rhsHash = hash(rhsString);
+      int lhsLength = lhsHash.length; // number of lines of first file
+      int rhsLength = rhsHash.length; // number of lines of second file
+
+      // opt[i][j] = length of LCS of x[i..M] and y[j..N]
+      int[][] opt = new int[lhsLength + 1][rhsLength + 1];
+      List<Point>[][] flags = new ArrayList[lhsLength + 1][rhsLength + 1];
+
+      // compute length of LCS and all subproblems via dynamic programming
+      for (int i = 0; i < lhsLength; i++) {
+         for (int j = 0; j < rhsLength; j++) {
+            if (lhsHash[i] == rhsHash[j]) {
+               // We are the same so continue the diagonal is intact
+               if (i == 0 || j == 0) {
+                  opt[i][j] = 0;
+               } else {
+                  opt[i][j] = opt[i - 1][j - 1] + 1;
+               }
+               costDiag(flags, i, j);
+            } else {
+               cleanIslands(flags, i, j);
+               if (i == 0 || j == 0) {
+                  opt[i][j] = 0;
+               } else {
+                  opt[i][j] = Math.max(opt[i - 1][j], opt[i][j - 1]);
+               }
+            }
+         }
+      }
+
+      // recover LCS itself and print out non-matching lines to standard output
+      int i = 0, j = 0;
+      while (i < lhsLength && j < rhsLength) {
+         // if the diagonal is in tact walk it
+         if (lhsHash[i] == rhsHash[j]) {
+            diffResult.add(DiffResult.TYPE.SAME, i, j);
+            i++;
+            j++;
+         }
+         // otherwise walk along the xx or y axis which is the longer
+         // this is not always the best approach. 
+         // we need to find the shortest path between {i,j} and the {i+ii,j+jj} which 
+         // connects us to the next diagonal run
+         else if (opt[i + 1][j] >= opt[i][j + 1]) {
+            diffResult.add(DiffResult.TYPE.LEFT, i, j);
+            System.out.println("lhs:" + i + "< " + lhsString[i++]);
+         } else {
+            diffResult.add(DiffResult.TYPE.RIGHT, i, j);
+            System.out.println("rhs:" + j + "> " + rhsString[j++]);
+         }
+      }
+
+      // dump out one remainder of one string if the other is exhausted
+      while (i < lhsLength || j < rhsLength) {
+         if (i == lhsLength) {
+            diffResult.add(DiffResult.TYPE.RIGHT, i, j);
+            System.out.println("lhs:" + i + "> " + rhsString[j++]);
+         } else if (j == rhsLength) {
+            diffResult.add(DiffResult.TYPE.LEFT, i, j);
+            System.out.println("rhs:" + j + "< " + lhsString[i++]);
+         }
+      }
+      return (diffResult);
+   }
+
+   public static boolean same(String left, String right) {
+      StringBuilder leftAll = new StringBuilder();
+
+      for (String s : left.replace("\n", "").split("  *")) {
+         leftAll.append(s);
+      }
+
+      StringBuilder rightAll = new StringBuilder();
+      for (String s : right.replace("\n", " ").split("  *")) {
+         rightAll.append(s);
+      }
+      boolean same = leftAll.toString().equals(rightAll.toString());
+      if (!same) {
+         String[] lhs = left.split("\n");
+         for (int i = 0; i < lhs.length; i++) {
+            lhs[i] = lhs[i].trim();
+         }
+         String[] rhs = right.split("\n");
+         for (int i = 0; i < rhs.length; i++) {
+            rhs[i] = rhs[i].trim();
+         }
+         diff(lhs, rhs);
+      }
+      return (same);
+   }
+
+}
diff --git a/test/codegen/src/java/com/amd/aparapi/KernelHelper.java b/test/codegen/src/java/com/amd/aparapi/KernelHelper.java
new file mode 100644
index 00000000..ec80168c
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/KernelHelper.java
@@ -0,0 +1,56 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+// contains some things that only tests would use
+// but in the com.amd.aparapi package for convenience
+
+public class KernelHelper{
+   public KernelHelper(Kernel kernel) {
+      this.kernel = kernel;
+      this.kernelRunner = kernel.getKernelRunner();
+   }
+
+   public boolean hasFP64Support() {
+      return kernelRunner.hasFP64Support();
+   }
+
+   Kernel kernel;
+
+   KernelRunner kernelRunner;
+}
diff --git a/test/codegen/src/java/com/amd/aparapi/Source.java b/test/codegen/src/java/com/amd/aparapi/Source.java
new file mode 100644
index 00000000..a08c2872
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/Source.java
@@ -0,0 +1,186 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Source{
+   enum STATE {
+      NONE,
+      JAVA,
+      OPENCL,
+      DOC
+   };
+
+   static final String OpenCLStart = "/**{OpenCL{";
+
+   static final String OpenCLEnd = "}OpenCL}**/";
+
+   static final String ThrowsStart = "/**{Throws{";
+
+   static final String ThrowsEnd = "}Throws}**/";
+
+   static final String DocStart = "/**";
+
+   static final String DocEnd = "*/";
+
+   Class<?> clazz;
+
+   File file;
+
+   Source.STATE state = STATE.NONE;
+
+   List<String> all = new ArrayList<String>();
+
+   List<List<String>> opencl = new ArrayList<List<String>>();
+
+   List<String> doc = new ArrayList<String>();
+
+   List<String> java = new ArrayList<String>();
+
+   List<String> exceptions = new ArrayList<String>();
+
+   public Source(Class<?> _clazz, File _rootDir) {
+      clazz = _clazz;
+      String srcName = clazz.getPackage().getName().replace(".", "/") + "/" + clazz.getSimpleName() + ".java";
+      file = new File(_rootDir, srcName);
+      try {
+         BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
+
+         state = STATE.JAVA;
+         List<String> openclSection = null;
+         for (String line = reader.readLine(); line != null; line = reader.readLine()) {
+            all.add(line);
+            String trimmedLine = line.trim();
+            switch (state) {
+               case JAVA:
+                  if (trimmedLine.equals(OpenCLStart)) {
+                     state = STATE.OPENCL;
+                     openclSection = new ArrayList<String>();
+                     opencl.add(openclSection);
+
+                  } else if (trimmedLine.startsWith(ThrowsStart) && trimmedLine.endsWith(ThrowsEnd)) {
+                     exceptions.add(trimmedLine.substring(ThrowsStart.length(), trimmedLine.length() - ThrowsEnd.length()));
+                  } else if (trimmedLine.equals(DocStart)) {
+                     state = STATE.DOC;
+                  } else {
+                     java.add(line);
+                  }
+                  break;
+               case OPENCL:
+                  if (trimmedLine.equals(OpenCLEnd)) {
+                     state = STATE.JAVA;
+                  } else {
+                     openclSection.add(line);
+                  }
+                  break;
+               case DOC:
+                  if (trimmedLine.equals(DocEnd)) {
+                     state = STATE.JAVA;
+                  } else {
+                     doc.add(line);
+                  }
+                  break;
+
+            }
+         }
+      } catch (FileNotFoundException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IOException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+
+   }
+
+   private String listToString(List<String> list) {
+      StringBuilder stringBuilder = new StringBuilder();
+      for (String line : list) {
+         stringBuilder.append(line).append("\n");
+      }
+      return (stringBuilder.toString().trim());
+   }
+
+   public String getOpenCLString(int _index) {
+      return (listToString(opencl.get(_index)));
+   }
+
+   public List<List<String>> getOpenCL() {
+      return (opencl);
+   }
+
+   public String getJavaString() {
+      return (listToString(java));
+   }
+
+   public List<String> getJava() {
+      return (java);
+   }
+
+   public File getFile() {
+      return (file);
+   }
+
+   public String getExceptionsString() {
+      return (listToString(exceptions));
+   }
+
+   public List<String> getExceptions() {
+      return (exceptions);
+   }
+
+   public String getDocString() {
+      return (listToString(doc));
+   }
+
+   public List<String> getDoc() {
+      return (doc);
+   }
+
+   public int getOpenCLSectionCount() {
+      return (opencl.size());
+   }
+}
diff --git a/test/codegen/src/java/com/amd/aparapi/SwingDiff.java b/test/codegen/src/java/com/amd/aparapi/SwingDiff.java
new file mode 100644
index 00000000..7a9def1a
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/SwingDiff.java
@@ -0,0 +1,203 @@
+/*
+Copyright (c) 2010-2011, Advanced Micro Devices, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer. 
+
+Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials provided with the distribution. 
+
+Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
+derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+If you use the software (in whole or in part), you shall adhere to all applicable U.S., European, and other export
+laws, including but not limited to the U.S. Export Administration Regulations ("EAR"), (15 C.F.R. Sections 730 through
+774), and E.U. Council Regulation (EC) No 1334/2000 of 22 June 2000.  Further, pursuant to Section 740.6 of the EAR,
+you hereby certify that, except pursuant to a license granted by the United States Department of Commerce Bureau of 
+Industry and Security or as otherwise permitted pursuant to a License Exception under the U.S. Export Administration 
+Regulations ("EAR"), you will not (1) export, re-export or release to a national of a country in Country Groups D:1,
+E:1 or E:2 any restricted technology, software, or source code you receive hereunder, or (2) export to Country Groups
+D:1, E:1 or E:2 the direct product of such technology or software, if such foreign produced direct product is subject
+to national security controls as identified on the Commerce Control List (currently found in Supplement 1 to Part 774
+of EAR).  For the most current Country Group listings, or for additional information about the EAR or your obligations
+under those regulations, please refer to the U.S. Bureau of Industry and Security's website at http://www.bis.doc.gov/. 
+
+*/
+package com.amd.aparapi;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextPane;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.DefaultStyledDocument;
+import javax.swing.text.Style;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyleContext;
+
+import com.amd.aparapi.Diff.DiffResult;
+
+public class SwingDiff{
+   JFrame frame;
+
+   public SwingDiff(DiffResult result) {
+      try {
+         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+
+         frame = new JFrame("SwingDiff");
+
+         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+         JPanel panel = new JPanel(){
+            @Override public void paint(Graphics g) {
+               super.paint(g);
+               g.drawRect(10, 10, 100, 100);
+            }
+         };
+         panel.setLayout(new BorderLayout());
+
+         StyleContext sc = new StyleContext();
+
+         // Create and add the style
+         final Style rootStyle = sc.addStyle("Root", null);
+         rootStyle.addAttribute(StyleConstants.Foreground, Color.black);
+         rootStyle.addAttribute(StyleConstants.FontSize, new Integer(12));
+         rootStyle.addAttribute(StyleConstants.FontFamily, "serif");
+         rootStyle.addAttribute(StyleConstants.Bold, new Boolean(false));
+         final Style heading1Style = sc.addStyle("Heading1", rootStyle);
+         heading1Style.addAttribute(StyleConstants.Foreground, Color.blue);
+
+         final Style heading2Style = sc.addStyle("Heading2", rootStyle);
+         heading2Style.addAttribute(StyleConstants.Foreground, Color.red);
+         heading2Style.addAttribute(StyleConstants.Background, Color.green);
+
+         final DefaultStyledDocument lhsdoc = new DefaultStyledDocument(sc);
+         JTextPane lhs = new JTextPane(lhsdoc);
+
+         lhsdoc.insertString(0, arrayToString(result.getLhs()), null);
+
+         // Finally, apply the style to the heading
+
+         lhsdoc.setParagraphAttributes(4, 1, heading2Style, false);
+         lhsdoc.setParagraphAttributes(20, 5, heading1Style, false);
+
+         lhs.setPreferredSize(new Dimension(800, 800));
+         final DefaultStyledDocument rhsdoc = new DefaultStyledDocument(sc);
+         JTextPane rhs = new JTextPane(rhsdoc);
+         rhsdoc.insertString(0, arrayToString(result.getRhs()), null);
+
+         rhsdoc.setParagraphAttributes(4, 1, heading2Style, false);
+         rhsdoc.setParagraphAttributes(20, 5, heading1Style, false);
+         rhs.setPreferredSize(new Dimension(800, 800));
+         panel.add(new JScrollPane(lhs), BorderLayout.WEST);
+         panel.add(new JScrollPane(rhs), BorderLayout.EAST);
+
+         // frame.setBackground(background);
+         frame.getContentPane().add(panel);
+         frame.pack();
+         frame.setVisible(true);
+      } catch (ClassNotFoundException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (InstantiationException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IllegalAccessException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (UnsupportedLookAndFeelException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (BadLocationException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+
+   }
+
+   public static void main(String[] args) {
+      String[] lhs = getFileContents("expected.c");
+      String[] rhs = getFileContents("actual.c");
+
+      DiffResult result = Diff.diff(lhs, rhs);
+      System.out.println(result);
+
+      SwingDiff swingDiff = new SwingDiff(result);
+   }
+
+   private static String arrayToString(String[] array) {
+      StringBuilder stringBuilder = new StringBuilder();
+      for (String line : array) {
+         stringBuilder.append(line).append("\n");
+      }
+      return (stringBuilder.toString().trim());
+   }
+
+   private static String[] getFileContents(String string) {
+      String[] content = null;
+      try {
+         BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(string)));
+         List<String> lines = new ArrayList<String>();
+         for (String line = reader.readLine(); line != null; line = reader.readLine()) {
+            lines.add(line);
+         }
+         reader.close();
+         content = lines.toArray(new String[0]);
+      } catch (FileNotFoundException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IOException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+      return (content);
+
+   }
+
+   private static String getFileContent(String string) {
+      String content = null;
+      try {
+         BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(string)));
+         StringBuilder sb = new StringBuilder();
+         for (String line = reader.readLine(); line != null; line = reader.readLine()) {
+            sb.append(line).append("\n");
+         }
+         reader.close();
+         content = sb.toString();
+      } catch (FileNotFoundException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      } catch (IOException e) {
+         // TODO Auto-generated catch block
+         e.printStackTrace();
+      }
+      return (content);
+
+   }
+
+}
diff --git a/test/codegen/src/java/com/amd/aparapi/test/AccessBooleanArray.java b/test/codegen/src/java/com/amd/aparapi/test/AccessBooleanArray.java
new file mode 100644
index 00000000..32ca87d6
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/AccessBooleanArray.java
@@ -0,0 +1,44 @@
+package com.amd.aparapi.test;
+
+public class AccessBooleanArray{
+   boolean[] ba = new boolean[1024];
+
+   public void run() {
+      for (int i = 0; i < 1024; i++) {
+         if (i % 2 == 0) {
+            ba[i] = true;
+         } else {
+            ba[i] = false;
+         }
+      }
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global char  *ba;
+    int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+
+__kernel void run(
+   __global char  *ba,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->ba = ba;
+   this->passid = passid;
+   {
+      for (int i = 0; i<1024; i++){
+         if ((i % 2)==0){
+            this->ba[i]  = 1;
+         } else {
+            this->ba[i]  = 0;
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/AccessByteArray.java b/test/codegen/src/java/com/amd/aparapi/test/AccessByteArray.java
new file mode 100644
index 00000000..890ff6a0
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/AccessByteArray.java
@@ -0,0 +1,47 @@
+package com.amd.aparapi.test;
+
+/**
+ * 
+ * Test whether we can assign a byte array element.
+ * @author gfrost
+ *
+ */
+public class AccessByteArray{
+   byte[] bytes = new byte[1024];
+
+   public void run() {
+
+      for (int i = 0; i < 1024; i++) {
+
+         bytes[i] = (byte) 1;
+
+      }
+
+   }
+}
+/**{OpenCL{
+ typedef struct This_s{
+   __global char  *bytes;
+   
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global char  *bytes,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->bytes = bytes;
+   this->passid = passid;
+   {
+      for (int i = 0; i<1024; i++){
+         this->bytes[i]  = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/AccessDoubleArray.java b/test/codegen/src/java/com/amd/aparapi/test/AccessDoubleArray.java
new file mode 100644
index 00000000..318d2ed8
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/AccessDoubleArray.java
@@ -0,0 +1,39 @@
+package com.amd.aparapi.test;
+
+public class AccessDoubleArray{
+   double[] doubles = new double[1024];
+
+   public void run() {
+
+      for (int i = 0; i < 1024; i++) {
+         doubles[i] = 1.0;
+      }
+   }
+}
+/**{OpenCL{
+#pragma OPENCL EXTENSION cl_amd_fp64 : enable
+
+typedef struct This_s{
+   __global double *doubles;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global double *doubles,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->doubles = doubles;
+   this->passid = passid;
+   {
+      for (int i = 0; i<1024; i++){
+         this->doubles[i]  = 1.0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/AccessFloatArray.java b/test/codegen/src/java/com/amd/aparapi/test/AccessFloatArray.java
new file mode 100644
index 00000000..45f2de6a
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/AccessFloatArray.java
@@ -0,0 +1,37 @@
+package com.amd.aparapi.test;
+
+public class AccessFloatArray{
+   float[] floats = new float[1024];
+
+   public void run() {
+      for (int i = 0; i < 1024; i++) {
+         floats[i] = 1f;
+      }
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global float *floats;
+
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global float *floats,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->floats = floats;
+   this->passid = passid;
+   {
+      for (int i = 0; i<1024; i++){
+         this->floats[i]  = 1.0f;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/AccessIntArray.java b/test/codegen/src/java/com/amd/aparapi/test/AccessIntArray.java
new file mode 100644
index 00000000..fca5117c
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/AccessIntArray.java
@@ -0,0 +1,37 @@
+package com.amd.aparapi.test;
+
+public class AccessIntArray{
+   int[] ints = new int[1024];
+
+   public void run() {
+      for (int i = 0; i < 1024; i++) {
+         ints[i] = 1;
+      }
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *ints;
+
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global int *ints,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->ints = ints;
+   this->passid = passid;
+   {
+      for (int i = 0; i<1024; i++){
+         this->ints[i]  = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/AccessLongArray.java b/test/codegen/src/java/com/amd/aparapi/test/AccessLongArray.java
new file mode 100644
index 00000000..ba4d6fd0
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/AccessLongArray.java
@@ -0,0 +1,37 @@
+package com.amd.aparapi.test;
+
+public class AccessLongArray{
+   long[] longs = new long[1024];
+
+   public void run() {
+      for (int i = 0; i < 1024; i++) {
+         longs[i] = 1;
+      }
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global long *longs;
+
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global long *longs,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->longs = longs;
+   this->passid = passid;
+   {
+      for (int i = 0; i<1024; i++){
+         this->longs[i]  = 1L;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/AccessShortArray.java b/test/codegen/src/java/com/amd/aparapi/test/AccessShortArray.java
new file mode 100644
index 00000000..345a0d1d
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/AccessShortArray.java
@@ -0,0 +1,37 @@
+package com.amd.aparapi.test;
+
+public class AccessShortArray{
+   short[] shorts = new short[1024];
+
+   public void run() {
+      for (int i = 0; i < 1024; i++) {
+         shorts[i] = 1;
+      }
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global short *shorts;
+
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global short *shorts,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->shorts = shorts;
+   this->passid = passid;
+   {
+      for (int i = 0; i<1024; i++){
+         this->shorts[i]  = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/AndOrAndPrecedence.java b/test/codegen/src/java/com/amd/aparapi/test/AndOrAndPrecedence.java
new file mode 100644
index 00000000..4aed5153
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/AndOrAndPrecedence.java
@@ -0,0 +1,44 @@
+package com.amd.aparapi.test;
+
+public class AndOrAndPrecedence{
+   public void run() {
+      boolean a = true;
+      boolean b = true;
+      boolean c = true;
+      boolean d = true;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (a && b || c && d) {
+         pass = true;
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char c = 1;
+      char d = 1;
+      char pass = 0;
+      if (a!=0 && b!=0 || c!=0 && d!=0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/AndOrPrecedence.java b/test/codegen/src/java/com/amd/aparapi/test/AndOrPrecedence.java
new file mode 100644
index 00000000..f427b54f
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/AndOrPrecedence.java
@@ -0,0 +1,42 @@
+package com.amd.aparapi.test;
+
+public class AndOrPrecedence{
+   public void run() {
+      boolean a = true;
+      boolean b = false;
+      boolean c = false;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (a || b && c) {
+         pass = true;
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 0;
+      char c = 0;
+      char pass = 0;
+      if (a!=0 || b!=0 && c!=0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/AndOrPrecedence2.java b/test/codegen/src/java/com/amd/aparapi/test/AndOrPrecedence2.java
new file mode 100644
index 00000000..4e2878bf
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/AndOrPrecedence2.java
@@ -0,0 +1,42 @@
+package com.amd.aparapi.test;
+
+public class AndOrPrecedence2{
+   public void run() {
+      boolean a = false;
+      boolean b = false;
+      boolean d = false;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (a && !(b && d)) {
+         pass = true;
+      }
+
+   }
+}
+/**{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 a = 0;
+      char b = 0;
+      char d = 0;
+      char pass = 0;
+      if (a!=0 && (b==0 || d==0)){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ArbitraryScope.java b/test/codegen/src/java/com/amd/aparapi/test/ArbitraryScope.java
new file mode 100644
index 00000000..1862abd0
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ArbitraryScope.java
@@ -0,0 +1,103 @@
+package com.amd.aparapi.test;
+
+public class ArbitraryScope{
+   int width = 1024;
+
+   float scale = 1f;
+
+   int maxIterations = 10;
+
+   public void run() {
+      int tid = 0;
+
+      int i = tid % width;
+      int j = tid / width;
+
+      float x0 = ((i * scale) - ((scale / 2) * width)) / width;
+      float y0 = ((j * scale) - ((scale / 2) * width)) / width;
+
+      float x = x0;
+      float y = y0;
+
+      float x2 = x * x;
+      float y2 = y * y;
+
+      {
+
+         float scaleSquare = scale * scale;
+
+         int count = 0;
+
+         for (int iter = 0; iter < maxIterations; ++iter) {
+            if (x2 + y2 <= scaleSquare) {
+               y = 2 * x * y + y0;
+               x = x2 - y2 + x0;
+
+               x2 = x * x;
+               y2 = y * y;
+               count++;
+            } else {
+               count--;
+            }
+         }
+         @SuppressWarnings("unused") int value = (256 * count) / maxIterations;
+      }
+
+      @SuppressWarnings("unused") float scaleSquare = 1f;
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   int width;
+   float scale;
+   int maxIterations;
+
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   int width,
+   float scale,
+   int maxIterations,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->width = width;
+   this->scale = scale;
+   this->maxIterations = maxIterations;
+   this->passid = passid;
+   {
+      int tid = 0;
+      int i = tid % this->width;
+      int j = tid / this->width;
+      float x0 = (((float)i * this->scale) - ((this->scale / 2.0f) * (float)this->width)) / (float)this->width;
+      float y0 = (((float)j * this->scale) - ((this->scale / 2.0f) * (float)this->width)) / (float)this->width;
+      float x = x0;
+      float y = y0;
+      float x2 = x * x;
+      float y2 = y * y;
+      {
+      float scaleSquare = this->scale * this->scale;
+      int count = 0;
+      for (int iter = 0; iter<this->maxIterations; iter++){
+         if ((x2 + y2)<=scaleSquare){
+            y = ((2.0f * x) * y) + y0;
+            x = (x2 - y2) + x0;
+            x2 = x * x;
+            y2 = y * y;
+            count++;
+         } else {
+            count--;
+         }
+      }
+      int value = (256 * count) / this->maxIterations;
+      }
+      float scaleSquare = 1.0f;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ArbitraryScope2.java b/test/codegen/src/java/com/amd/aparapi/test/ArbitraryScope2.java
new file mode 100644
index 00000000..6ada6924
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ArbitraryScope2.java
@@ -0,0 +1,104 @@
+package com.amd.aparapi.test;
+
+public class ArbitraryScope2{
+   int width = 1024;
+
+   float scale = 1f;
+
+   int maxIterations = 10;
+
+   public void run() {
+      int tid = 0;
+
+      int i = tid % width;
+      int j = tid / width;
+
+      float x0 = ((i * scale) - ((scale / 2) * width)) / width;
+      float y0 = ((j * scale) - ((scale / 2) * width)) / width;
+
+      float x = x0;
+      float y = y0;
+
+      float x2 = x * x;
+      float y2 = y * y;
+
+      {
+         int count = 0;
+         count++;
+      }
+
+      float scaleSquare = scale * scale;
+
+      int count = 0;
+
+      for (int iter = 0; iter < maxIterations; ++iter) {
+         if (x2 + y2 <= scaleSquare) {
+            y = 2 * x * y + y0;
+            x = x2 - y2 + x0;
+
+            x2 = x * x;
+            y2 = y * y;
+            count++;
+         } else {
+            count--;
+         }
+      }
+      @SuppressWarnings("unused") int value = (256 * count) / maxIterations;
+
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   int width;
+   float scale;
+   int maxIterations;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+
+__kernel void run(
+   int width,
+   float scale,
+   int maxIterations,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->width = width;
+   this->scale = scale;
+   this->maxIterations = maxIterations;
+   this->passid = passid;
+   {
+      int tid = 0;
+      int i = tid % this->width;
+      int j = tid / this->width;
+      float x0 = (((float)i * this->scale) - ((this->scale / 2.0f) * (float)this->width)) / (float)this->width;
+      float y0 = (((float)j * this->scale) - ((this->scale / 2.0f) * (float)this->width)) / (float)this->width;
+      float x = x0;
+      float y = y0;
+      float x2 = x * x;
+      float y2 = y * y;
+      {
+      int count = 0;
+      count++;
+      }
+      float scaleSquare = this->scale * this->scale;
+      int count = 0;
+      for (int iter = 0; iter<this->maxIterations; iter++){
+         if ((x2 + y2)<=scaleSquare){
+            y = ((2.0f * x) * y) + y0;
+            x = (x2 - y2) + x0;
+            x2 = x * x;
+            y2 = y * y;
+            count++;
+         } else {
+            count--;
+         }
+      }
+      int value = (256 * count) / this->maxIterations;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ArbitraryScopeSimple.java b/test/codegen/src/java/com/amd/aparapi/test/ArbitraryScopeSimple.java
new file mode 100644
index 00000000..82b447ae
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ArbitraryScopeSimple.java
@@ -0,0 +1,47 @@
+package com.amd.aparapi.test;
+
+public class ArbitraryScopeSimple{
+
+   public void run() {
+      int value = 10;
+      {
+         int count = 10;
+         float f = 10f;
+         value = (int) (count * f);
+      }
+      @SuppressWarnings("unused") int result = 0;
+      int count = 0;
+      result = value + count;
+
+   }
+}
+/**{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;
+   {
+      int value = 10;
+      {
+         int count = 10;
+         float f = 10.0f;
+         value = (int)((float)count * f);
+      }
+      int result = 0;
+      int count = 0;
+      result = value + count;
+      return;
+   }
+}
+
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/AssignAndPassAsParameter.java b/test/codegen/src/java/com/amd/aparapi/test/AssignAndPassAsParameter.java
new file mode 100644
index 00000000..f30d4ed0
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/AssignAndPassAsParameter.java
@@ -0,0 +1,50 @@
+package com.amd.aparapi.test;
+
+public class AssignAndPassAsParameter{
+
+   final static int START_SIZE = 128;
+
+   public int[] values = new int[START_SIZE];
+
+   public int[] results = new int[START_SIZE];
+
+   int actuallyDoIt(int a) {
+      return 1;
+   }
+
+   int y = 2;
+
+   public void run() {
+      actuallyDoIt(results[y] = actuallyDoIt(y));
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *results;
+   int y;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+int com_amd_aparapi_test_AssignAndPassAsParameter__actuallyDoIt(This *this, int a){
+   return(1);
+}
+__kernel void run(
+   __global int *results, 
+   int y,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->results = results;
+   this->y = y;
+   this->passid = passid;
+   {
+      com_amd_aparapi_test_AssignAndPassAsParameter__actuallyDoIt(this, this->results[this->y]  = com_amd_aparapi_test_AssignAndPassAsParameter__actuallyDoIt(this, this->y));
+      return;
+   }
+}
+
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/AssignAndPassAsParameterSimple.java b/test/codegen/src/java/com/amd/aparapi/test/AssignAndPassAsParameterSimple.java
new file mode 100644
index 00000000..90a22bea
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/AssignAndPassAsParameterSimple.java
@@ -0,0 +1,14 @@
+package com.amd.aparapi.test;
+
+public class AssignAndPassAsParameterSimple{
+
+   void actuallyDoIt(int a) {
+
+   }
+
+   public void run() {
+      @SuppressWarnings("unused") int z;
+      actuallyDoIt(z = 1);
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/AssignField.java b/test/codegen/src/java/com/amd/aparapi/test/AssignField.java
new file mode 100644
index 00000000..ccc177e1
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/AssignField.java
@@ -0,0 +1,10 @@
+package com.amd.aparapi.test;
+
+public class AssignField{
+   int field = 1024;
+
+   public void run() {
+      field = 100;
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/Atomic32Pragma.java b/test/codegen/src/java/com/amd/aparapi/test/Atomic32Pragma.java
new file mode 100644
index 00000000..5c9a0068
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/Atomic32Pragma.java
@@ -0,0 +1,43 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class Atomic32Pragma extends Kernel{
+
+   final int[] values = new int[10];
+
+   @Override public void run() {
+      atomicAdd(values, 1, 1);
+   }
+}
+
+/**{OpenCL{
+#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
+int atomicAdd(__global int *_arr, int _index, int _delta){
+   return atomic_add(&_arr[_index], _delta);
+}
+typedef struct This_s{
+   __global int *values;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global int *values,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->values = values;
+   this->passid = passid;
+   {
+      atomicAdd(this->values, 1, 1);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/BooleanToggle.java b/test/codegen/src/java/com/amd/aparapi/test/BooleanToggle.java
new file mode 100644
index 00000000..2ed1ede4
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/BooleanToggle.java
@@ -0,0 +1,50 @@
+package com.amd.aparapi.test;
+
+public class BooleanToggle{
+   public void run() {
+      boolean pass = false;
+
+      pass = !pass;
+
+   }
+}
+/**{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;
+      pass = (pass==0)?1:0;
+      return;
+   }
+}
+}OpenCL}**/
+/**{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;
+      pass = (pass!=0)?0:1;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/Break.java b/test/codegen/src/java/com/amd/aparapi/test/Break.java
new file mode 100644
index 00000000..3f912c3d
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/Break.java
@@ -0,0 +1,14 @@
+package com.amd.aparapi.test;
+
+public class Break{
+   public void run() {
+      @SuppressWarnings("unused") boolean pass = false;
+      for (int i = 0; i < 10; i++) {
+         if (i == 5) {
+            break;
+         }
+         pass = true;
+      }
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ByteParams.java b/test/codegen/src/java/com/amd/aparapi/test/ByteParams.java
new file mode 100644
index 00000000..507a6905
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ByteParams.java
@@ -0,0 +1,45 @@
+package com.amd.aparapi.test;
+
+public class ByteParams{
+
+   // input for addEmUp2
+   byte[] test = new byte[4];
+
+   byte addEmUp2(byte x, byte y) {
+      return (byte) ((byte) x + (byte) y);
+   }
+
+   public void run() {
+
+      @SuppressWarnings("unused") byte bb = 0;
+      byte cc = 7;
+
+      addEmUp2((bb = cc), cc);
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+char com_amd_aparapi_test_ByteParams__addEmUp2(This *this, char x, char y){
+   return((char )(x + y));
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      char bb = 0;
+      char cc = 7;
+      com_amd_aparapi_test_ByteParams__addEmUp2(this, bb = cc, cc);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ByteParamsSimple.java b/test/codegen/src/java/com/amd/aparapi/test/ByteParamsSimple.java
new file mode 100644
index 00000000..2f8f9ddc
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ByteParamsSimple.java
@@ -0,0 +1,42 @@
+package com.amd.aparapi.test;
+
+public class ByteParamsSimple{
+
+   void addEmUp2(byte x, byte y) {
+
+   }
+
+   public void run() {
+
+      byte bb = 0;
+      byte cc = 7;
+
+      addEmUp2(bb, cc);
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+void com_amd_aparapi_test_ByteParamsSimple__addEmUp2(This *this, char x, char y){
+   return;
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      char bb = 0;
+      char cc = 7;
+      com_amd_aparapi_test_ByteParamsSimple__addEmUp2(this, bb, cc);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/CallGetPassId.java b/test/codegen/src/java/com/amd/aparapi/test/CallGetPassId.java
new file mode 100644
index 00000000..01e544cd
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/CallGetPassId.java
@@ -0,0 +1,31 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class CallGetPassId extends Kernel{
+   public void run() {
+      int thePassId = getPassId();
+   }
+
+}
+/**{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;
+   {
+      int thePassId = get_pass_id(this);
+      return;
+   }
+}
+
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/CallObject.java b/test/codegen/src/java/com/amd/aparapi/test/CallObject.java
new file mode 100644
index 00000000..dc7d9dc0
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/CallObject.java
@@ -0,0 +1,20 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class CallObject extends Kernel{
+   static class Dummy{
+      public int foo() {
+         return 42;
+      }
+   };
+
+   Dummy dummy = new Dummy();
+
+   public void run() {
+      out[0] = dummy.foo();
+   }
+
+   int out[] = new int[2];
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/CallObjectStatic.java b/test/codegen/src/java/com/amd/aparapi/test/CallObjectStatic.java
new file mode 100644
index 00000000..017ae676
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/CallObjectStatic.java
@@ -0,0 +1,19 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class CallObjectStatic extends Kernel{
+   static class Dummy{
+      static public int foo() {
+         return 42;
+      }
+   };
+
+   public void run() {
+      out[0] = Dummy.foo();
+   }
+
+   int out[] = new int[2];
+}
+
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/CallRunSuper.java b/test/codegen/src/java/com/amd/aparapi/test/CallRunSuper.java
new file mode 100644
index 00000000..fca5c0c0
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/CallRunSuper.java
@@ -0,0 +1,47 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+class CallRunSuperBase extends Kernel{
+   @Override public void run() {
+      out[0] = 2;
+   }
+
+   int out[] = new int[2];
+}
+
+public class CallRunSuper extends CallRunSuperBase{
+   public void run() {
+      super.run();
+      out[1] = 3;
+   }
+
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *out;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+void com_amd_aparapi_test_CallRunSuperBase__run(This *this){
+   this->out[0]  = 2;
+   return;
+}
+__kernel void run(
+   __global int *out,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->out = out;
+   this->passid = passid;
+   {
+      com_amd_aparapi_test_CallRunSuperBase__run(this);
+      this->out[1]  = 3;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/CallSuper.java b/test/codegen/src/java/com/amd/aparapi/test/CallSuper.java
new file mode 100644
index 00000000..df91c998
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/CallSuper.java
@@ -0,0 +1,50 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+abstract class CallSuperBase extends Kernel{
+   int foo(int n) {
+      return n * 2;
+   }
+}
+
+public class CallSuper extends CallSuperBase{
+   public void run() {
+      out[0] = foo(2);
+   }
+
+   int foo(int n) {
+      return 1 + super.foo(n);
+   }
+
+   int out[] = new int[1];
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *out;  
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+int com_amd_aparapi_test_CallSuperBase__foo(This *this, int n){
+   return((n * 2));
+}
+int com_amd_aparapi_test_CallSuper__foo(This *this, int n){
+   return((1 + com_amd_aparapi_test_CallSuperBase__foo(this, n)));
+}
+__kernel void run(
+   __global int *out,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->out = out;
+   this->passid = passid;
+   {
+      this->out[0]  = com_amd_aparapi_test_CallSuper__foo(this, 2);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/CallTwice.java b/test/codegen/src/java/com/amd/aparapi/test/CallTwice.java
new file mode 100644
index 00000000..b25adc65
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/CallTwice.java
@@ -0,0 +1,42 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class CallTwice extends Kernel{
+
+   public int getOne() {
+      return (1);
+   }
+
+   @Override public void run() {
+      out[0] = getOne() + getOne();
+   }
+
+   int out[] = new int[1];
+}
+
+/**{OpenCL{
+typedef struct This_s{
+   __global int *out;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+int com_amd_aparapi_test_CallTwice__getOne(This *this){
+   return(1);
+}
+__kernel void run(
+   __global int *out, 
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->out = out;
+   this->passid = passid;
+   {
+      this->out[0]  = com_amd_aparapi_test_CallTwice__getOne(this) + com_amd_aparapi_test_CallTwice__getOne(this);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/CharArrayField.java b/test/codegen/src/java/com/amd/aparapi/test/CharArrayField.java
new file mode 100644
index 00000000..fdf9706e
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/CharArrayField.java
@@ -0,0 +1,13 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class CharArrayField extends Kernel{
+   @Override public void run() {
+      out[0] = 0;
+   }
+
+   char out[] = new char[1];
+}
+
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/CharAsParameter.java b/test/codegen/src/java/com/amd/aparapi/test/CharAsParameter.java
new file mode 100644
index 00000000..3c630d02
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/CharAsParameter.java
@@ -0,0 +1,21 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class CharAsParameter extends Kernel{
+
+   public char doIt(char x) {
+      return x;
+   }
+
+   @Override public void run() {
+      byte b = 0x1;
+
+      doIt('A');
+
+      doIt((char) b);
+
+   }
+}
+
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/CharType.java b/test/codegen/src/java/com/amd/aparapi/test/CharType.java
new file mode 100644
index 00000000..34417cc4
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/CharType.java
@@ -0,0 +1,14 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class CharType extends Kernel{
+   @Override public void run() {
+      char c = Character.MAX_VALUE;
+      out[0] = c;
+   }
+
+   int out[] = new int[1];
+}
+
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ClassHasStaticFieldAccess.java b/test/codegen/src/java/com/amd/aparapi/test/ClassHasStaticFieldAccess.java
new file mode 100644
index 00000000..ea061b7e
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ClassHasStaticFieldAccess.java
@@ -0,0 +1,16 @@
+package com.amd.aparapi.test;
+
+public class ClassHasStaticFieldAccess{
+   int[] ints = new int[1024];
+
+   static int foo = 6;
+
+   public void run() {
+      for (int i = 0; i < 1024; i++) {
+         if (i % 2 == 0) {
+            ints[i] = foo;
+         }
+      }
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ClassHasStaticMethod.java b/test/codegen/src/java/com/amd/aparapi/test/ClassHasStaticMethod.java
new file mode 100644
index 00000000..8be389b5
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ClassHasStaticMethod.java
@@ -0,0 +1,22 @@
+package com.amd.aparapi.test;
+
+public class ClassHasStaticMethod{
+   int[] ints = new int[1024];
+
+   static int getIntAndReturnIt(int a) {
+      return (int) (((int) 1) - a);
+   }
+
+   public void run() {
+      int foo = 1;
+      for (int i = 0; i < 1024; i++) {
+         if (i % 2 == 0) {
+            ints[i] = foo;
+         } else {
+            ints[i] = getIntAndReturnIt(foo);
+            ;
+         }
+      }
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ClassHasStaticMethodSimple.java b/test/codegen/src/java/com/amd/aparapi/test/ClassHasStaticMethodSimple.java
new file mode 100644
index 00000000..2bc74cf8
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ClassHasStaticMethodSimple.java
@@ -0,0 +1,14 @@
+package com.amd.aparapi.test;
+
+public class ClassHasStaticMethodSimple{
+
+   static void staticMethod() {
+
+   }
+
+   public void run() {
+      staticMethod();
+
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/CompositeArbitraryScope.java b/test/codegen/src/java/com/amd/aparapi/test/CompositeArbitraryScope.java
new file mode 100644
index 00000000..664db5b5
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/CompositeArbitraryScope.java
@@ -0,0 +1,183 @@
+package com.amd.aparapi.test;
+
+// this example gave the following error:
+/// com.amd.aparapi.classtools.writer.CodeGenException: composite COMPOSITE_ARBITRARY_SCOPE
+
+import com.amd.aparapi.Kernel;
+
+public class CompositeArbitraryScope extends Kernel{
+
+   void t5() {
+      int gid = getGlobalId();
+      int numRemaining = 1;
+      int thisCount = 0;
+      while (numRemaining > 0 && gid > 0) {
+         numRemaining += 1;
+         thisCount = min(numRemaining, gid);
+         numRemaining -= thisCount;
+         numRemaining += 1;
+      }
+      gid -= thisCount;
+   }
+
+   void t4() {
+      int gid = getGlobalId();
+      int numRemaining = 1;
+      while (numRemaining > 0 && gid > 0) {
+         numRemaining += 1;
+         int thisCount = min(numRemaining, gid);
+         numRemaining -= thisCount;
+         numRemaining += 1;
+         gid--;
+      }
+   }
+
+   void t3() {
+      int gid = getGlobalId();
+      int numRemaining = 1;
+      while (numRemaining > 0) {
+         numRemaining += 1;
+         int thisCount = min(numRemaining, gid);
+         numRemaining -= thisCount;
+         numRemaining += 1;
+      }
+   }
+
+   void t2() {
+      int gid = getGlobalId();
+      int numRemaining = 1;
+      while (numRemaining > 0) {
+         {
+            int thisCount = min(numRemaining, gid);
+            numRemaining -= thisCount;
+         }
+         numRemaining += 0;
+      }
+   }
+
+   void t1() {
+      int gid = getGlobalId();
+      int numRemaining = 1;
+      while (numRemaining > 0) {
+         numRemaining += 1;
+         int thisCount = min(numRemaining, gid);
+         numRemaining -= thisCount;
+      }
+   }
+
+   @Override public void run() {
+      int gid = getGlobalId();
+      int numRemaining = 1;
+
+      t1();
+      t2();
+      t3();
+      t4();
+      t5();
+
+      while (numRemaining > 0) {
+         numRemaining += 1;
+         {
+            int thisCount = min(numRemaining, gid);
+            numRemaining -= thisCount;
+         }
+      }
+   }
+}
+
+/**{OpenCL{
+typedef struct This_s{
+   
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+void com_amd_aparapi_test_CompositeArbitraryScope__t5(This *this){
+   int gid = get_global_id(0);
+   int numRemaining = 1;
+   int thisCount = 0;
+   for (; numRemaining>0 && gid>0; numRemaining++){
+      numRemaining++;
+      thisCount = min(numRemaining, gid);
+      numRemaining = numRemaining - thisCount;
+   }
+   gid = gid - thisCount;
+   return;
+}
+void com_amd_aparapi_test_CompositeArbitraryScope__t4(This *this){
+   int gid = get_global_id(0);
+   int numRemaining = 1;
+   while (numRemaining>0 && gid>0){
+      numRemaining++;
+      {
+         int thisCount = min(numRemaining, gid);
+         numRemaining = numRemaining - thisCount;
+         numRemaining++;
+         gid--;
+      }
+   }
+   return;
+}
+void com_amd_aparapi_test_CompositeArbitraryScope__t3(This *this){
+   int gid = get_global_id(0);
+   int numRemaining = 1;
+   while (numRemaining>0){
+      numRemaining++;
+      {
+         int thisCount = min(numRemaining, gid);
+         numRemaining = numRemaining - thisCount;
+         numRemaining++;
+      }
+   }
+   return;
+}
+void com_amd_aparapi_test_CompositeArbitraryScope__t2(This *this){
+   int gid = get_global_id(0);
+   int numRemaining = 1;
+   for (; numRemaining>0; numRemaining){
+      {
+         int thisCount = min(numRemaining, gid);
+         numRemaining = numRemaining - thisCount;
+      }
+   }
+   return;
+}
+void com_amd_aparapi_test_CompositeArbitraryScope__t1(This *this){
+   int gid = get_global_id(0);
+   int numRemaining = 1;
+   while (numRemaining>0){
+      numRemaining++;
+      {
+         int thisCount = min(numRemaining, gid);
+         numRemaining = numRemaining - thisCount;
+      }
+   }
+   return;
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      int gid = get_global_id(0);
+      int numRemaining = 1;
+      com_amd_aparapi_test_CompositeArbitraryScope__t1(this);
+      com_amd_aparapi_test_CompositeArbitraryScope__t2(this);
+      com_amd_aparapi_test_CompositeArbitraryScope__t3(this);
+      com_amd_aparapi_test_CompositeArbitraryScope__t4(this);
+      com_amd_aparapi_test_CompositeArbitraryScope__t5(this);
+      while (numRemaining>0){
+         numRemaining++;
+         {
+            int thisCount = min(numRemaining, gid);
+            numRemaining = numRemaining - thisCount;
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ConstantAssignInExpression.java b/test/codegen/src/java/com/amd/aparapi/test/ConstantAssignInExpression.java
new file mode 100644
index 00000000..d3cfeccc
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ConstantAssignInExpression.java
@@ -0,0 +1,39 @@
+package com.amd.aparapi.test;
+
+public class ConstantAssignInExpression{
+
+   void func(int _arg) {
+      // nada
+   }
+
+   public void run() {
+      @SuppressWarnings("unused") int result = 1;
+      func(result = 0);
+
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+void com_amd_aparapi_test_ConstantAssignInExpression__func(This *this, int _arg){
+   return;
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      int result = 1;
+      com_amd_aparapi_test_ConstantAssignInExpression__func(this, result=0);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/Continue.java b/test/codegen/src/java/com/amd/aparapi/test/Continue.java
new file mode 100644
index 00000000..13728385
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/Continue.java
@@ -0,0 +1,40 @@
+package com.amd.aparapi.test;
+
+public class Continue{
+   public void run() {
+      @SuppressWarnings("unused") boolean pass = false;
+      for (int i = 0; i < 10; i++) {
+         if (i == 5) {
+            continue;
+         }
+         pass = true;
+      }
+   }
+}
+/**{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;
+      for (int i = 0; i<10; i++){
+         if (i==5){
+         } else {
+            pass = 1;
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ContinueTorture.java b/test/codegen/src/java/com/amd/aparapi/test/ContinueTorture.java
new file mode 100644
index 00000000..9bbb96b5
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ContinueTorture.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class ContinueTorture{
+
+   final static int START_SIZE = 128;
+
+   public int[] values = new int[START_SIZE];
+
+   public int[] results = new int[START_SIZE];
+
+   int actuallyDoIt(int a) {
+      return 1;
+   }
+
+   int actuallyDoIt2(int a) {
+      return -1;
+   }
+
+   int myId = 34;
+
+   public void run() {
+      int idx = myId;
+      while (--idx > 0) {
+
+         if (myId == 0) {
+            continue;
+         }
+         if (myId % 2 == 0) {
+            results[myId] = actuallyDoIt(idx);
+            continue;
+         } else {
+            results[myId] = actuallyDoIt2(idx);
+            continue;
+         }
+      }
+   }
+}
+//**{Throws{ClassParseException}Throws}**/
\ No newline at end of file
diff --git a/test/codegen/src/java/com/amd/aparapi/test/DirectRecursion.java b/test/codegen/src/java/com/amd/aparapi/test/DirectRecursion.java
new file mode 100644
index 00000000..efefdebf
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/DirectRecursion.java
@@ -0,0 +1,19 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class DirectRecursion extends Kernel{
+
+   public void run() {
+      intout[0] = fact(10);
+      @SuppressWarnings("unused") boolean pass = false;
+   }
+
+   int fact(int n) {
+      return (n <= 1 ? n : n * fact(n - 1));
+   }
+
+   int intout[] = new int[1];
+
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/Drem.java b/test/codegen/src/java/com/amd/aparapi/test/Drem.java
new file mode 100644
index 00000000..052a5750
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/Drem.java
@@ -0,0 +1,45 @@
+package com.amd.aparapi.test;
+
+public class Drem{
+   public void run() {
+      out[0] = m % n;
+   }
+
+   double out[] = new double[10];
+
+   double m;
+
+   double n;
+}
+
+/**{OpenCL{
+#pragma OPENCL EXTENSION cl_amd_fp64 : enable
+
+typedef struct This_s{
+   __global double *out;
+   double m;
+   double n;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+__kernel void run(
+   __global double *out, 
+   double m, 
+   double n, 
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->out = out;
+   this->m = m;
+   this->n = n;
+   this->passid = passid;
+   {
+      this->out[0]  = this->m % this->n;
+      return;
+   }
+}
+
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/EmptyWhileWithInc.java b/test/codegen/src/java/com/amd/aparapi/test/EmptyWhileWithInc.java
new file mode 100644
index 00000000..71bc9343
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/EmptyWhileWithInc.java
@@ -0,0 +1,28 @@
+package com.amd.aparapi.test;
+
+public class EmptyWhileWithInc{
+   public void run() {
+      int x = 0;
+      while (x++ < 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;
+   {
+      for (int x = 0; x++<10;){}
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/EntrypointRecursion.java b/test/codegen/src/java/com/amd/aparapi/test/EntrypointRecursion.java
new file mode 100644
index 00000000..76ee6423
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/EntrypointRecursion.java
@@ -0,0 +1,20 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class EntrypointRecursion extends Kernel{
+
+   int[] values = new int[128];
+
+   public void run() {
+      int id = getGlobalId();
+
+      values[id]++;
+
+      if (values[id] < 20) {
+         run();
+      }
+   }
+
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/Ex.java b/test/codegen/src/java/com/amd/aparapi/test/Ex.java
new file mode 100644
index 00000000..80daaec7
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/Ex.java
@@ -0,0 +1,37 @@
+package com.amd.aparapi.test;
+
+public class Ex{
+   public void run() {
+      int total = 0;
+      for (int i = 0; i < 100; i++) {
+         if (i % 10 == 0 && i % 4 == 0) {
+            total++;
+         }
+      }
+   }
+}
+/**{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;
+   {
+      int total = 0;
+      for (int i = 0; i<100; i++){
+         if ((i % 10)==0 && (i % 4)==0){
+            total++;
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/FirstAssignInExpression.java b/test/codegen/src/java/com/amd/aparapi/test/FirstAssignInExpression.java
new file mode 100644
index 00000000..09a888c5
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/FirstAssignInExpression.java
@@ -0,0 +1,42 @@
+package com.amd.aparapi.test;
+
+public class FirstAssignInExpression{
+
+   void func(int _arg) {
+      // nada
+   }
+
+   int y = 2;
+
+   public void run() {
+      int value = 1;
+      @SuppressWarnings("unused") int result;
+      func(result = value);
+
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+void func(This *this, int _arg){
+   return;
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      int result;
+      func(this, result = 0);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/FirstAssignInExpression2.java b/test/codegen/src/java/com/amd/aparapi/test/FirstAssignInExpression2.java
new file mode 100644
index 00000000..f37a8799
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/FirstAssignInExpression2.java
@@ -0,0 +1,48 @@
+package com.amd.aparapi.test;
+
+public class FirstAssignInExpression2{
+
+   public void run() {
+      int value = 1;
+      int assignMe;
+      int result = 0;
+      if (value == value) {
+         result = assignMe = value;
+      } else {
+         assignMe = 1;
+         result = 2;
+      }
+      result++;
+      assignMe++;
+
+   }
+}
+/**{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;
+   {
+      int value = 1;
+      int result=0;
+      int assignMe=0;
+      if (true){
+         result = assignMe = value;
+      }else{
+         assignMe =1;
+         result=2;
+      }
+      result++;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/FloatParams.java b/test/codegen/src/java/com/amd/aparapi/test/FloatParams.java
new file mode 100644
index 00000000..f838f3dd
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/FloatParams.java
@@ -0,0 +1,44 @@
+package com.amd.aparapi.test;
+
+public class FloatParams{
+
+   int addEmUp(float y, float z) {
+      return ((int) y + (int) z);
+   }
+
+   public void run() {
+
+      int y = 2;
+
+      float x = 0f;
+
+      addEmUp((x = (float) y), x);
+
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+int com_amd_aparapi_test_FloatParams__addEmUp(This *this, float y, float z){
+   return(((int)y + (int)z));
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      int y = 2;
+      float x = 0.0f;
+      com_amd_aparapi_test_FloatParams__addEmUp(this, x=(float)y, x);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/FloatParamsSimple.java b/test/codegen/src/java/com/amd/aparapi/test/FloatParamsSimple.java
new file mode 100644
index 00000000..1b580585
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/FloatParamsSimple.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class FloatParamsSimple{
+
+   void floatParams(float y) {
+
+   }
+
+   public void run() {
+
+      floatParams(0f);
+
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+void com_amd_aparapi_test_FloatParamsSimple__floatParams(This *this, float y){
+   return;
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      com_amd_aparapi_test_FloatParamsSimple__floatParams(this, 0.0f);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/For.java b/test/codegen/src/java/com/amd/aparapi/test/For.java
new file mode 100644
index 00000000..4a79388a
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/For.java
@@ -0,0 +1,33 @@
+package com.amd.aparapi.test;
+
+public class For{
+   public void run() {
+      @SuppressWarnings("unused") boolean pass = false;
+      for (int i = 0; i < 10; i++) {
+         pass = true;
+      }
+
+   }
+}
+/**{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;
+      for (int i = 0; i<10; i++){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ForAnd.java b/test/codegen/src/java/com/amd/aparapi/test/ForAnd.java
new file mode 100644
index 00000000..221e4e59
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ForAnd.java
@@ -0,0 +1,35 @@
+package com.amd.aparapi.test;
+
+public class ForAnd{
+   public void run() {
+      @SuppressWarnings("unused") boolean pass = false;
+      for (int i = 0; i > 2 && i < 10; i++) {
+         pass = true;
+      }
+
+   }
+}
+/**{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;
+      for (int i = 0; i>2 && i<10; i++){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ForAndMandel.java b/test/codegen/src/java/com/amd/aparapi/test/ForAndMandel.java
new file mode 100644
index 00000000..95220660
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ForAndMandel.java
@@ -0,0 +1,87 @@
+package com.amd.aparapi.test;
+
+public class ForAndMandel{
+   int width = 1024;
+
+   float scale = 1f;
+
+   int maxIterations = 10;
+
+   public void run() {
+      int tid = 0;
+
+      int i = tid % width;
+      int j = tid / width;
+
+      float x0 = ((i * scale) - ((scale / 2) * width)) / width;
+      float y0 = ((j * scale) - ((scale / 2) * width)) / width;
+
+      float x = x0;
+      float y = y0;
+
+      float x2 = x * x;
+      float y2 = y * y;
+
+      float scaleSquare = scale * scale;
+
+      int count = 0;
+
+      for (int iter = 0; x2 + y2 <= scaleSquare && (iter < maxIterations); ++iter) {
+
+         y = 2 * x * y + y0;
+         x = x2 - y2 + x0;
+
+         x2 = x * x;
+         y2 = y * y;
+         count++;
+      }
+      @SuppressWarnings("unused") int value = (256 * count) / maxIterations;
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   int width;
+   float scale;
+   int maxIterations;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   int width,
+   float scale,
+   int maxIterations,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->width = width;
+   this->scale = scale;
+   this->maxIterations = maxIterations;
+   this->passid = passid;
+   {
+      int tid = 0;
+      int i = tid % this->width;
+      int j = tid / this->width;
+      float x0 = (((float)i * this->scale) - ((this->scale / 2.0f) * (float)this->width)) / (float)this->width;
+      float y0 = (((float)j * this->scale) - ((this->scale / 2.0f) * (float)this->width)) / (float)this->width;
+      float x = x0;
+      float y = y0;
+      float x2 = x * x;
+      float y2 = y * y;
+      float scaleSquare = this->scale * this->scale;
+      int count = 0;
+      for (int iter = 0; (x2 + y2)<=scaleSquare && iter<this->maxIterations; iter++){
+         y = ((2.0f * x) * y) + y0;
+         x = (x2 - y2) + x0;
+         x2 = x * x;
+         y2 = y * y;
+         count++;
+      }
+      int value = (256 * count) / this->maxIterations;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ForAndMandelNoInitialize.java b/test/codegen/src/java/com/amd/aparapi/test/ForAndMandelNoInitialize.java
new file mode 100644
index 00000000..eed60ec2
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ForAndMandelNoInitialize.java
@@ -0,0 +1,88 @@
+package com.amd.aparapi.test;
+
+public class ForAndMandelNoInitialize{
+   int width = 1024;
+
+   float scale = 1f;
+
+   int maxIterations = 10;
+
+   public void run() {
+      int tid = 0;
+
+      int i = tid % width;
+      int j = tid / width;
+
+      float x0 = ((i * scale) - ((scale / 2) * width)) / width;
+      float y0 = ((j * scale) - ((scale / 2) * width)) / width;
+
+      float x = x0;
+      float y = y0;
+
+      float x2 = x * x;
+      float y2 = y * y;
+
+      float scaleSquare = scale * scale;
+
+      int count = 0;
+      int iter = 0;
+      for (; (x2 + y2 <= scaleSquare) && (iter < maxIterations); ++iter) {
+
+         y = 2 * x * y + y0;
+         x = x2 - y2 + x0;
+
+         x2 = x * x;
+         y2 = y * y;
+         count++;
+      }
+      @SuppressWarnings("unused") int value = (256 * count) / maxIterations;
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   int width;
+   float scale;
+   int maxIterations;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   int width, 
+   float scale, 
+   int maxIterations,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->width = width;
+   this->scale = scale;
+   this->maxIterations = maxIterations;
+   this->passid = passid;
+   {
+      int tid = 0;
+      int i = tid % this->width;
+      int j = tid / this->width;
+      float x0 = (((float)i * this->scale) - ((this->scale / 2.0f) * (float)this->width)) / (float)this->width;
+      float y0 = (((float)j * this->scale) - ((this->scale / 2.0f) * (float)this->width)) / (float)this->width;
+      float x = x0;
+      float y = y0;
+      float x2 = x * x;
+      float y2 = y * y;
+      float scaleSquare = this->scale * this->scale;
+      int count = 0;
+      int iter = 0;
+      for (; (x2 + y2)<=scaleSquare && iter<this->maxIterations; iter++){
+         y = ((2.0f * x) * y) + y0;
+         x = (x2 - y2) + x0;
+         x2 = x * x;
+         y2 = y * y;
+         count++;
+      }
+      int value = (256 * count) / this->maxIterations;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ForAsFirst.java b/test/codegen/src/java/com/amd/aparapi/test/ForAsFirst.java
new file mode 100644
index 00000000..21ca4db4
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ForAsFirst.java
@@ -0,0 +1,33 @@
+package com.amd.aparapi.test;
+
+public class ForAsFirst{
+
+   public void run() {
+
+      for (int i = 0; i < 1; i++) {
+
+      }
+   }
+}
+/**{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;
+   {
+      for (int i = 0; i<1; i++){
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ForBooleanToggle.java b/test/codegen/src/java/com/amd/aparapi/test/ForBooleanToggle.java
new file mode 100644
index 00000000..76636e4a
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ForBooleanToggle.java
@@ -0,0 +1,60 @@
+package com.amd.aparapi.test;
+
+public class ForBooleanToggle{
+   public void run() {
+      boolean pass = false;
+      for (int i = 0; i > 2 && i < 10; i++) {
+         pass = !pass;
+      }
+
+   }
+}
+/**{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;
+      for (int i = 0; i>2 && i<10; i++){
+         pass = (pass==0)?1:0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
+
+/**{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;
+      for (int i = 0; i>2 && i<10; i++){
+         pass = (pass!=0)?0:1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ForBreak.java b/test/codegen/src/java/com/amd/aparapi/test/ForBreak.java
new file mode 100644
index 00000000..d70d519e
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ForBreak.java
@@ -0,0 +1,18 @@
+package com.amd.aparapi.test;
+
+public class ForBreak{
+   public void run() {
+      @SuppressWarnings("unused") boolean pass = false;
+      for (int i = 0; i > 2 && i < 10; i++) {
+         pass = false;
+         if (i == 5 || i == 6) {
+            if (i == 5) {
+               pass = true;
+               break;
+            }
+         }
+      }
+
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ForEach.java b/test/codegen/src/java/com/amd/aparapi/test/ForEach.java
new file mode 100644
index 00000000..4ab0eb0d
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ForEach.java
@@ -0,0 +1,18 @@
+package com.amd.aparapi.test;
+
+public class ForEach{
+
+   public void run() {
+      int max = Integer.MIN_VALUE;
+      for (int i : in) {
+         if (i > max)
+            max = i;
+      }
+      out[0] = max;
+   }
+
+   int out[] = new int[10];
+
+   int in[] = new int[10];
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ForIf.java b/test/codegen/src/java/com/amd/aparapi/test/ForIf.java
new file mode 100644
index 00000000..8cf2f7e3
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ForIf.java
@@ -0,0 +1,39 @@
+package com.amd.aparapi.test;
+
+public class ForIf{
+   public void run() {
+      @SuppressWarnings("unused") boolean pass = false;
+      for (int i = 0; i > 2; i++) {
+         if (i == 3) {
+            pass = true;
+         }
+      }
+
+   }
+}
+/**{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;
+      for (int i = 0; i>2; i++){
+         if (i==3){
+            pass = 1;
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ForIfMandel.java b/test/codegen/src/java/com/amd/aparapi/test/ForIfMandel.java
new file mode 100644
index 00000000..8864ad3f
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ForIfMandel.java
@@ -0,0 +1,94 @@
+package com.amd.aparapi.test;
+
+public class ForIfMandel{
+   int width = 1024;
+
+   float scale = 1f;
+
+   int maxIterations = 10;
+
+   public void run() {
+      int tid = 0;
+
+      int i = tid % width;
+      int j = tid / width;
+
+      float x0 = ((i * scale) - ((scale / 2) * width)) / width;
+      float y0 = ((j * scale) - ((scale / 2) * width)) / width;
+
+      float x = x0;
+      float y = y0;
+
+      float x2 = x * x;
+      float y2 = y * y;
+
+      float scaleSquare = scale * scale;
+
+      int count = 0;
+
+      for (int iter = 0; iter < maxIterations; ++iter) {
+         if (x2 + y2 <= scaleSquare) {
+            y = 2 * x * y + y0;
+            x = x2 - y2 + x0;
+
+            x2 = x * x;
+            y2 = y * y;
+            count++;
+         } else {
+            count--;
+         }
+      }
+      @SuppressWarnings("unused") int value = (256 * count) / maxIterations;
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   int width;
+   float scale;
+   int maxIterations;  
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   int width, 
+   float scale, 
+   int maxIterations,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->width = width;
+   this->scale = scale;
+   this->maxIterations = maxIterations;
+   this->passid = passid;
+   {
+      int tid = 0;
+      int i = tid % this->width;
+      int j = tid / this->width;
+      float x0 = (((float)i * this->scale) - ((this->scale / 2.0f) * (float)this->width)) / (float)this->width;
+      float y0 = (((float)j * this->scale) - ((this->scale / 2.0f) * (float)this->width)) / (float)this->width;
+      float x = x0;
+      float y = y0;
+      float x2 = x * x;
+      float y2 = y * y;
+      float scaleSquare = this->scale * this->scale;
+      int count = 0;
+      for (int iter = 0; iter<this->maxIterations; iter++){
+         if ((x2 + y2)<=scaleSquare){
+            y = ((2.0f * x) * y) + y0;
+            x = (x2 - y2) + x0;
+            x2 = x * x;
+            y2 = y * y;
+            count++;
+         } else {
+            count--;
+         }
+      }
+      int value = (256 * count) / this->maxIterations;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/Frem.java b/test/codegen/src/java/com/amd/aparapi/test/Frem.java
new file mode 100644
index 00000000..305f5e5c
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/Frem.java
@@ -0,0 +1,42 @@
+package com.amd.aparapi.test;
+
+public class Frem{
+   public void run() {
+      out[0] = m % n;
+   }
+
+   float out[] = new float[10];
+
+   float m;
+
+   float n;
+}
+
+/**{OpenCL{
+typedef struct This_s{
+   __global float *out;
+   float m;
+   float n;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+__kernel void run(
+   __global float *out, 
+   float m, 
+   float n, 
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->out = out;
+   this->m = m;
+   this->n = n;
+   this->passid = passid;
+   {
+      this->out[0]  = this->m % this->n;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IEEERemainderDouble.java b/test/codegen/src/java/com/amd/aparapi/test/IEEERemainderDouble.java
new file mode 100644
index 00000000..e9a294c3
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IEEERemainderDouble.java
@@ -0,0 +1,47 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class IEEERemainderDouble extends Kernel{
+   public void run() {
+      out[0] = IEEEremainder(m, n);
+   }
+
+   double out[] = new double[10];
+
+   double m;
+
+   double n;
+}
+
+/**{OpenCL{
+#pragma OPENCL EXTENSION cl_amd_fp64 : enable
+
+typedef struct This_s{
+   __global double *out;
+   double m;
+   double n;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+__kernel void run(
+   __global double *out, 
+   double m, 
+   double n, 
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->out = out;
+   this->m = m;
+   this->n = n;
+   this->passid = passid;
+   {
+      this->out[0]  = remainder(this->m, this->n);
+      return;
+   }
+}
+
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IEEERemainderFloat.java b/test/codegen/src/java/com/amd/aparapi/test/IEEERemainderFloat.java
new file mode 100644
index 00000000..bf3ba63b
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IEEERemainderFloat.java
@@ -0,0 +1,45 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class IEEERemainderFloat extends Kernel{
+   public void run() {
+      out[0] = IEEEremainder(m, n);
+   }
+
+   float out[] = new float[10];
+
+   float m;
+
+   float n;
+}
+
+/**{OpenCL{
+typedef struct This_s{
+   __global float *out;
+   float m;
+   float n;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+__kernel void run(
+   __global float *out, 
+   float m, 
+   float n, 
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->out = out;
+   this->m = m;
+   this->n = n;
+   this->passid = passid;
+   {
+      this->out[0]  = remainder(this->m, this->n);
+      return;
+   }
+}
+
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/If.java b/test/codegen/src/java/com/amd/aparapi/test/If.java
new file mode 100644
index 00000000..449c767e
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/If.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class If{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (testValue % 4 == 0) {
+         pass = true;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if ( (testValue % 4) == 0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfAnd.java b/test/codegen/src/java/com/amd/aparapi/test/IfAnd.java
new file mode 100644
index 00000000..c891f00c
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfAnd.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class IfAnd{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (testValue >= 0 && testValue < 100) {
+         pass = true;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if (testValue>=0 && testValue<100){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfAndAnd.java b/test/codegen/src/java/com/amd/aparapi/test/IfAndAnd.java
new file mode 100644
index 00000000..344c07ce
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfAndAnd.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class IfAndAnd{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (testValue >= 0 && testValue < 100 && testValue == 20) {
+         pass = true;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if (testValue>=0 && testValue<100 && testValue==20){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfAndAndAnd.java b/test/codegen/src/java/com/amd/aparapi/test/IfAndAndAnd.java
new file mode 100644
index 00000000..34f8028e
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfAndAndAnd.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class IfAndAndAnd{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (testValue % 2 == 0 && testValue <= 10 && testValue >= 0 && testValue % 4 == 0) {
+         pass = true;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if ((testValue % 2)==0 && testValue<=10 && testValue>=0 && (testValue % 4)==0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfAndOrAnd.java b/test/codegen/src/java/com/amd/aparapi/test/IfAndOrAnd.java
new file mode 100644
index 00000000..a7044f15
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfAndOrAnd.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class IfAndOrAnd{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (testValue % 2 == 0 && testValue <= 10 || testValue >= 0 && testValue % 4 == 0) {
+         pass = true;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if ((testValue % 2)==0 && testValue<=10 || testValue>=0 && (testValue % 4)==0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfBooleanAndAndAnd.java b/test/codegen/src/java/com/amd/aparapi/test/IfBooleanAndAndAnd.java
new file mode 100644
index 00000000..5bd5a8f6
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfBooleanAndAndAnd.java
@@ -0,0 +1,41 @@
+package com.amd.aparapi.test;
+
+public class IfBooleanAndAndAnd{
+   public void run() {
+      boolean a = true, b = true, c = true, d = true;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (a && b && c && d) {
+         pass = true;
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char c = 1;
+      char d = 1;
+      char pass = 0;
+      if (a!=0 && b!=0 && c!=0 && d!=0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfBooleanAndAndOr.java b/test/codegen/src/java/com/amd/aparapi/test/IfBooleanAndAndOr.java
new file mode 100644
index 00000000..39e7f3c9
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfBooleanAndAndOr.java
@@ -0,0 +1,41 @@
+package com.amd.aparapi.test;
+
+public class IfBooleanAndAndOr{
+   public void run() {
+      boolean a = true, b = true, c = true, d = true;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (a && b && c || d) {
+         pass = true;
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char c = 1;
+      char d = 1;
+      char pass = 0;
+      if (a!=0 && b!=0 && c!=0 || d!=0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfBooleanAndOrAnd.java b/test/codegen/src/java/com/amd/aparapi/test/IfBooleanAndOrAnd.java
new file mode 100644
index 00000000..f8a55a25
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfBooleanAndOrAnd.java
@@ -0,0 +1,41 @@
+package com.amd.aparapi.test;
+
+public class IfBooleanAndOrAnd{
+   public void run() {
+      boolean a = true, b = true, c = true, d = true;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (a && b || c && d) {
+         pass = true;
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char c = 1;
+      char d = 1;
+      char pass = 0;
+      if (a!=0 && b!=0 || c!=0 && d!=0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfBooleanAndOrOr.java b/test/codegen/src/java/com/amd/aparapi/test/IfBooleanAndOrOr.java
new file mode 100644
index 00000000..b829a188
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfBooleanAndOrOr.java
@@ -0,0 +1,41 @@
+package com.amd.aparapi.test;
+
+public class IfBooleanAndOrOr{
+   public void run() {
+      boolean a = true, b = true, c = true, d = true;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (a && b && c || d) {
+         pass = true;
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char c = 1;
+      char d = 1;
+      char pass = 0;
+      if (a!=0 && b!=0 && c!=0 || d!=0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfBooleanOrAndAnd.java b/test/codegen/src/java/com/amd/aparapi/test/IfBooleanOrAndAnd.java
new file mode 100644
index 00000000..aba3cc26
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfBooleanOrAndAnd.java
@@ -0,0 +1,41 @@
+package com.amd.aparapi.test;
+
+public class IfBooleanOrAndAnd{
+   public void run() {
+      boolean a = true, b = true, c = true, d = true;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (a || b && c && d) {
+         pass = true;
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char c = 1;
+      char d = 1;
+      char pass = 0;
+      if (a!=0 || b!=0 && c!=0 && d!=0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfBooleanOrAndOr.java b/test/codegen/src/java/com/amd/aparapi/test/IfBooleanOrAndOr.java
new file mode 100644
index 00000000..cebff431
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfBooleanOrAndOr.java
@@ -0,0 +1,44 @@
+package com.amd.aparapi.test;
+
+public class IfBooleanOrAndOr{
+   public void run() {
+      boolean a = true;
+      boolean b = true;
+      boolean c = true;
+      boolean d = true;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (a || b && c || d) {
+         pass = true;
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char c = 1;
+      char d = 1;
+      char pass = 0;
+      if (a!=0 || b!=0 && c!=0 || d!=0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfBooleanOrOrAnd.java b/test/codegen/src/java/com/amd/aparapi/test/IfBooleanOrOrAnd.java
new file mode 100644
index 00000000..b180f17a
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfBooleanOrOrAnd.java
@@ -0,0 +1,41 @@
+package com.amd.aparapi.test;
+
+public class IfBooleanOrOrAnd{
+   public void run() {
+      boolean a = true, b = true, c = true, d = true;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (a || b || c && d) {
+         pass = true;
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char c = 1;
+      char d = 1;
+      char pass = 0;
+      if (a!=0 || b!=0 || c!=0 && d!=0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfBooleanOrOrOr.java b/test/codegen/src/java/com/amd/aparapi/test/IfBooleanOrOrOr.java
new file mode 100644
index 00000000..8d18b789
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfBooleanOrOrOr.java
@@ -0,0 +1,41 @@
+package com.amd.aparapi.test;
+
+public class IfBooleanOrOrOr{
+   public void run() {
+      boolean a = true, b = true, c = true, d = true;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (a || b || c || d) {
+         pass = true;
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char c = 1;
+      char d = 1;
+      char pass = 0;
+      if (a!=0 || b!=0 || c!=0 || d!=0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfElse.java b/test/codegen/src/java/com/amd/aparapi/test/IfElse.java
new file mode 100644
index 00000000..773a9d36
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfElse.java
@@ -0,0 +1,42 @@
+package com.amd.aparapi.test;
+
+public class IfElse{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (testValue % 4 == 0) {
+         pass = true;
+      } else {
+         pass = false;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if ( (testValue % 4) == 0){
+         pass = 1;
+      } else {
+         pass = 0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfElseAnd.java b/test/codegen/src/java/com/amd/aparapi/test/IfElseAnd.java
new file mode 100644
index 00000000..e089c0d5
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfElseAnd.java
@@ -0,0 +1,42 @@
+package com.amd.aparapi.test;
+
+public class IfElseAnd{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (testValue >= 0 && testValue < 100) {
+         pass = true;
+      } else {
+         pass = false;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if (testValue>=0 && testValue<100){
+         pass = 1;
+      } else {
+         pass = 0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfElseAndAndAnd.java b/test/codegen/src/java/com/amd/aparapi/test/IfElseAndAndAnd.java
new file mode 100644
index 00000000..4eac6d87
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfElseAndAndAnd.java
@@ -0,0 +1,42 @@
+package com.amd.aparapi.test;
+
+public class IfElseAndAndAnd{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (testValue % 2 == 0 && testValue <= 10 && testValue >= 0 && testValue % 4 == 0) {
+         pass = true;
+      } else {
+         pass = false;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if ((testValue % 2)==0 && testValue<=10 && testValue>=0 && (testValue % 4)==0){
+         pass = 1;
+      } else {
+         pass = 0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfElseIfElseIfElse.java b/test/codegen/src/java/com/amd/aparapi/test/IfElseIfElseIfElse.java
new file mode 100644
index 00000000..a96015da
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfElseIfElseIfElse.java
@@ -0,0 +1,105 @@
+package com.amd.aparapi.test;
+
+public class IfElseIfElseIfElse{
+   /*
+     1:   istore_1   (0:iconst_1)
+     3:   istore_2   (2:iconst_1)
+     5:   istore_3   (4:iconst_1)
+     7:   istore  4  (6:iconst_0)
+     10:  ifeq    16 (9:iload_1)      ?
+     13:  goto    39                  | +
+     17:  ifeq    26 (16:  iload_2)   v | ?
+     21:  istore  4  (20:  iconst_1)    | |
+     23:  goto    39                    | | +
+     27:  ifeq    36 (26:  iload_3)     | v | ?
+     31:  istore  4  (30:  iconst_1)    |   | |
+     33:  goto    39                    |   | | +
+     37:  istore  4  (36:  iconst_1)    |   | v |
+     39:  return                        v   v   v
+    */
+   public void run() {
+      boolean a = true;
+      boolean b = true;
+      boolean c = true;
+      @SuppressWarnings("unused") boolean result = false;
+
+      if (a) {
+      } else if (b) {
+         result = true;
+      } else if (c) {
+         result = true;
+      } else {
+         result = true;
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char c = 1;
+      char result = 0;
+      if (a!=0){
+      } else {
+         if (b!=0){
+            result = 1;
+         } else {
+            if (c!=0){
+               result = 1;
+            } else {
+               result = 1;
+            }
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
+/**{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 a = 1;
+      char b = 1;
+      char c = 1;
+      char result = 0;
+      if (a==0){
+         if (b!=0){
+            result = 1;
+         } else {
+            if (c!=0){
+               result = 1;
+            } else {
+               result = 1;
+            }
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfElseNot__OrOr_And_.java b/test/codegen/src/java/com/amd/aparapi/test/IfElseNot__OrOr_And_.java
new file mode 100644
index 00000000..0289da06
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfElseNot__OrOr_And_.java
@@ -0,0 +1,42 @@
+package com.amd.aparapi.test;
+
+public class IfElseNot__OrOr_And_{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (!((testValue % 2 == 0 || testValue <= 0 || testValue >= 100) && testValue % 4 == 0)) {
+         pass = true;
+      } else {
+         pass = false;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if ((testValue % 2)!=0 && testValue>0 && testValue<100 || (testValue % 4)!=0){
+         pass = 1;
+      } else {
+         pass = 0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfElseOrOrAnd.java b/test/codegen/src/java/com/amd/aparapi/test/IfElseOrOrAnd.java
new file mode 100644
index 00000000..dbf8cbac
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfElseOrOrAnd.java
@@ -0,0 +1,42 @@
+package com.amd.aparapi.test;
+
+public class IfElseOrOrAnd{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (testValue % 2 == 0 || testValue <= 0 || testValue >= 100 && testValue % 4 == 0) {
+         pass = true;
+      } else {
+         pass = false;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if ((testValue % 2)==0 || testValue<=0 || testValue>=100 && (testValue % 4)==0){
+         pass = 1;
+      } else {
+         pass = 0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfElseOrOrOr.java b/test/codegen/src/java/com/amd/aparapi/test/IfElseOrOrOr.java
new file mode 100644
index 00000000..558a193d
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfElseOrOrOr.java
@@ -0,0 +1,42 @@
+package com.amd.aparapi.test;
+
+public class IfElseOrOrOr{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (testValue % 2 == 0 || testValue <= 0 || testValue >= 100 || testValue == 10) {
+         pass = true;
+      } else {
+         pass = false;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if ((testValue % 2)==0 || testValue<=0 || testValue>=100 || testValue==10){
+         pass = 1;
+      } else {
+         pass = 0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfElse_And_Or_And.java b/test/codegen/src/java/com/amd/aparapi/test/IfElse_And_Or_And.java
new file mode 100644
index 00000000..891e1e5c
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfElse_And_Or_And.java
@@ -0,0 +1,45 @@
+package com.amd.aparapi.test;
+
+public class IfElse_And_Or_And{
+   public void run() {
+      int x = 5;
+      int y = 5;
+
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if ((x >= 0 && x < 10) || (y >= 0 && y < 10)) {
+         pass = true;
+      } else {
+         pass = false;
+      }
+
+   }
+}
+/**{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;
+   {
+      int x = 5;
+      int y = 5;
+      char pass = 0;
+      if (x>=0 && x<10 || y>=0 && y<10){
+         pass = 1;
+      } else {
+         pass = 0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfElse_OrOr_And.java b/test/codegen/src/java/com/amd/aparapi/test/IfElse_OrOr_And.java
new file mode 100644
index 00000000..42c5f442
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfElse_OrOr_And.java
@@ -0,0 +1,42 @@
+package com.amd.aparapi.test;
+
+public class IfElse_OrOr_And{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if ((testValue % 2 == 0 || testValue <= 0 || testValue >= 100) && testValue % 4 == 0) {
+         pass = true;
+      } else {
+         pass = false;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if (((testValue % 2)==0 || testValue<=0 || testValue>=100) && (testValue % 4)==0){
+         pass = 1;
+      } else {
+         pass = 0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfElse_Or_And_Or.java b/test/codegen/src/java/com/amd/aparapi/test/IfElse_Or_And_Or.java
new file mode 100644
index 00000000..8a522c5b
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfElse_Or_And_Or.java
@@ -0,0 +1,45 @@
+package com.amd.aparapi.test;
+
+public class IfElse_Or_And_Or{
+   public void run() {
+      int x = 5;
+      int y = 5;
+
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if ((x < 0 || x >= 10) && (y < 0 || y >= 10)) {
+         pass = true;
+      } else {
+         pass = false;
+      }
+
+   }
+}
+/**{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;
+   {
+      int x = 5;
+      int y = 5;
+      char pass = 0;
+      if ((x<0 || x>=10) && (y<0 || y>=10)){
+         pass = 1;
+      } else {
+         pass = 0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfOr.java b/test/codegen/src/java/com/amd/aparapi/test/IfOr.java
new file mode 100644
index 00000000..3f26971b
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfOr.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class IfOr{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (testValue >= 0 || testValue < 100) {
+         pass = true;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if (testValue>=0 || testValue<100){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfOrAndOr.java b/test/codegen/src/java/com/amd/aparapi/test/IfOrAndOr.java
new file mode 100644
index 00000000..9b8408c7
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfOrAndOr.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class IfOrAndOr{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (testValue % 2 == 0 || testValue <= 0 && testValue >= 100 || testValue % 4 == 0) {
+         pass = true;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if ((testValue % 2)==0 || testValue<=0 && testValue>=100 || (testValue % 4)==0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfOrOr.java b/test/codegen/src/java/com/amd/aparapi/test/IfOrOr.java
new file mode 100644
index 00000000..f4f447cd
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfOrOr.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class IfOrOr{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (testValue >= 0 || testValue < 100 || testValue == 20) {
+         pass = true;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if (testValue>=0 || testValue<100 || testValue==20){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfOrOrAnd.java b/test/codegen/src/java/com/amd/aparapi/test/IfOrOrAnd.java
new file mode 100644
index 00000000..32ce782c
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfOrOrAnd.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class IfOrOrAnd{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (testValue % 2 == 0 || testValue <= 0 || testValue >= 100 && testValue % 4 == 0) {
+         pass = true;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if ((testValue % 2)==0 || testValue<=0 || testValue>=100 && (testValue % 4)==0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IfOrOrOr.java b/test/codegen/src/java/com/amd/aparapi/test/IfOrOrOr.java
new file mode 100644
index 00000000..3f6f051a
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IfOrOrOr.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class IfOrOrOr{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if (testValue % 2 == 0 || testValue <= 0 || testValue >= 100 || testValue == 10) {
+         pass = true;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if ((testValue % 2)==0 || testValue<=0 || testValue>=100 || testValue==10){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/If_IfElseIfElseElse_Else.java b/test/codegen/src/java/com/amd/aparapi/test/If_IfElseIfElseElse_Else.java
new file mode 100644
index 00000000..e778c809
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/If_IfElseIfElseElse_Else.java
@@ -0,0 +1,60 @@
+package com.amd.aparapi.test;
+
+public class If_IfElseIfElseElse_Else{
+   public void run() {
+      boolean a = true;
+      boolean b = true;
+      boolean c = true;
+      @SuppressWarnings("unused") boolean result = false;
+
+      if (a) {
+         if (b) {
+            result = true;
+         } else if (c) {
+            result = true;
+         } else {
+            result = true;
+         }
+      } else {
+         result = false;
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char c = 1;
+      char result = 0;
+      if (a!=0){
+         if (b!=0){
+            result = 1;
+         } else {
+            if (c!=0){
+               result = 1;
+            } else {
+               result = 1;
+            }
+         }
+      } else {
+         result = 0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/If_IfElse_Else.java b/test/codegen/src/java/com/amd/aparapi/test/If_IfElse_Else.java
new file mode 100644
index 00000000..c3b7acd0
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/If_IfElse_Else.java
@@ -0,0 +1,52 @@
+package com.amd.aparapi.test;
+
+public class If_IfElse_Else{
+   public void run() {
+      boolean a = true;
+      boolean b = true;
+      @SuppressWarnings("unused") boolean result = false;
+
+      if (a) {
+         if (b) {
+            result = true;
+         } else {
+            result = true;
+         }
+      } else {
+         result = false;
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char result = 0;
+      if (a!=0){
+         if (b!=0){
+            result = 1;
+         } else {
+            result = 1;
+         }
+      } else {
+         result = 0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/If_IfElse_Else_IfElse_.java b/test/codegen/src/java/com/amd/aparapi/test/If_IfElse_Else_IfElse_.java
new file mode 100644
index 00000000..5c0ff1ad
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/If_IfElse_Else_IfElse_.java
@@ -0,0 +1,126 @@
+package com.amd.aparapi.test;
+
+public class If_IfElse_Else_IfElse_{
+   /*
+      1:  istore_1   ( 0:   iconst_1)
+      3:  istore_2   ( 2:   iconst_1)
+      5:  istore_3   ( 4:   iconst_1)
+      7:  istore  4  ( 6:   iconst_1)
+     10:  istore  5  ( 9:   iconst_0)
+     13:  ifeq    50 (12:  iload_1)              ?
+     17:  ifeq    36 (16:  iload_2)              | ?
+     21:  ifeq    30 (20:  iload_3)              | | ?
+     25:  istore  5  (24:  iconst_1)             | | |
+     27:  goto    50                             | | | +
+     31:  istore  5  (30:  iconst_2)             | | v |
+     33:  goto    50                             | |   | +
+     38:  ifeq    47 (36:  iload   4)            | v   | | ?            !!!!!!!  
+     42:  istore  5  (41:  iconst_3)             |     | | |
+     44:  goto    50                             |     | | | +
+     48:  istore  5  (47:  iconst_4)             |     | | v |
+     50:  return                                 v     v v   v
+
+
+
+      1:  istore_1   ( 0:   iconst_1)
+      3:  istore_2   ( 2:   iconst_1)
+      5:  istore_3   ( 4:   iconst_1)
+      7:  istore  4  ( 6:   iconst_1)
+     10:  istore  5  ( 9:   iconst_0)
+     13:  ifeq    50 (12:  iload_1)              ?
+     17:  ifeq    36 (16:  iload_2)              | ?
+     21:  IFELSE                                 | | 
+     33:  goto    50                             | | | +
+     38:  ifeq    47 (36:  iload   4)            | v | | ?              !!!!!!!!
+     42:  istore  5  (41:  iconst_3)             |   | | |
+     44:  goto    50                             |   | | | +
+     48:  istore  5  (47:  iconst_4)             |   | | v |
+     50:  return                                 v   v v   v
+
+      1:  istore_1   ( 0:   iconst_1)
+      3:  istore_2   ( 2:   iconst_1)
+      5:  istore_3   ( 4:   iconst_1)
+      7:  istore  4  ( 6:   iconst_1)
+     10:  istore  5  ( 9:   iconst_0)
+     13:  ifeq    50 (12:  iload_1)              ?
+     17:  ifeq    36 (16:  iload_2)              | ? <----   ignore this
+     21:  IFELSE                                 | | 
+     33:  goto    50                             | | +
+     38:  IFELSE                                 | v | 
+     50:  return                                 v   v   
+
+      1:  istore_1   ( 0:   iconst_1)
+      3:  istore_2   ( 2:   iconst_1)
+      5:  istore_3   ( 4:   iconst_1)
+      7:  istore  4  ( 6:   iconst_1)
+     10:  istore  5  ( 9:   iconst_0)
+     13:  ifeq    50 (12:  iload_1)              ?
+     21:  IFELSE                                 |  
+     33:  goto    50                             | +
+     38:  IFELSE                                 | |
+     50:  return                                 v v
+     */
+   public void run() {
+      boolean a = true;
+      boolean b = true;
+      boolean c = true;
+      boolean d = true;
+      @SuppressWarnings("unused") int count = 0;
+      if (a) {
+         if (b) {
+            if (c) {
+               count = 1;
+            } else {
+               count = 2;
+            }
+         } else {
+            if (d) {
+               count = 3;
+            } else {
+               count = 4;
+            }
+         }
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char c = 1;
+      char d = 1;
+      int count = 0;
+      if (a!=0){
+         if (b!=0){
+            if (c!=0){
+               count = 1;
+            } else {
+               count = 2;
+            }
+         } else {
+            if (d!=0){
+               count = 3;
+            } else {
+               count = 4;
+            }
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/If_If_Else.java b/test/codegen/src/java/com/amd/aparapi/test/If_If_Else.java
new file mode 100644
index 00000000..937fdf61
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/If_If_Else.java
@@ -0,0 +1,59 @@
+package com.amd.aparapi.test;
+
+public class If_If_Else{
+   /*
+   1:   istore_1   (0:   iconst_1)
+   3:   istore_2   (2:   iconst_1)
+   5:   istore_3   (4:   iconst_0)
+   7:   ifeq    19 (6:   iload_1)    ?
+   11:  ifeq    21 (10:  iload_2)    | ?
+   15:  istore_3   (14:  iconst_1)   | |
+   16:  goto    21                   | | +
+   20:  istore_3   (19:  iconst_0)   v | |
+   21:  return                         v v
+    */
+   public void run() {
+      boolean a = true;
+      boolean b = true;
+      @SuppressWarnings("unused") boolean result = false;
+
+      if (a) {
+         if (b) {
+            result = true;
+         }
+      } else {
+         result = false;
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char result = 0;
+      if (a!=0){
+         if (b!=0){
+            result = 1;
+         } 
+      } else {
+         result = 0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/If_If_Else2.java b/test/codegen/src/java/com/amd/aparapi/test/If_If_Else2.java
new file mode 100644
index 00000000..3576d6da
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/If_If_Else2.java
@@ -0,0 +1,44 @@
+package com.amd.aparapi.test;
+
+public class If_If_Else2{
+   public void run() {
+      boolean a = true;
+      boolean b = true;
+      @SuppressWarnings("unused") boolean result = false;
+
+      if (a && b) {
+         result = true;
+      } else {
+         result = false;
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char result = 0;
+      if (a!=0 && b!=0){
+         result = 1;
+      } else {
+         result = 0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/If_If_Else_If_.java b/test/codegen/src/java/com/amd/aparapi/test/If_If_Else_If_.java
new file mode 100644
index 00000000..adee7b9c
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/If_If_Else_If_.java
@@ -0,0 +1,64 @@
+package com.amd.aparapi.test;
+
+public class If_If_Else_If_{
+   /*
+   1:   istore_1   (0:iconst_1)
+   3:   istore_2   (2:iconst_1)
+   5:   istore_3   (4:iconst_0)
+   7:   ifeq    19 (6:iload_1)    ?
+   11:  ifeq    25 (10:iload_2)   | ?
+   15:  istore_3   (14:iconst_1)  | |
+   16:  goto    25                | | +
+   20:  ifeq    25 (19:iload_2)   v | | ?
+   24:  istore_3   (23:iconst_1)    | | |
+   25:  return                      v v v
+    */
+   public void run() {
+      boolean a = true;
+      boolean b = true;
+      @SuppressWarnings("unused") boolean result = false;
+
+      if (a) {
+         if (b) {
+            result = true;
+         }
+      } else {
+         if (b) {
+            result = true;
+         }
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char result = 0;
+      if (a!=0){
+         if (b!=0){
+            result = 1;
+         }
+      } else {
+         if (b!=0){
+            result = 1;
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/If_OrOr_And.java b/test/codegen/src/java/com/amd/aparapi/test/If_OrOr_And.java
new file mode 100644
index 00000000..0df343f7
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/If_OrOr_And.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class If_OrOr_And{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if ((testValue % 2 == 0 || testValue <= 0 || testValue >= 100) && testValue % 4 == 0) {
+         pass = true;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if (((testValue % 2)==0 || testValue<=0 || testValue>=100) && (testValue % 4)==0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/If_While_Else.java b/test/codegen/src/java/com/amd/aparapi/test/If_While_Else.java
new file mode 100644
index 00000000..56084799
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/If_While_Else.java
@@ -0,0 +1,44 @@
+package com.amd.aparapi.test;
+
+public class If_While_Else{
+   public void run() {
+      boolean a = true;
+
+      if (a) {
+         while (a) {
+            a = false;
+         }
+      } else {
+         a = true;
+
+      }
+
+   }
+}
+/**{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 a = 1;
+      if (a!=0){
+         for (; a!=0; a = 0){
+         }
+      } else {
+         a = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/If_While_Else_While.java b/test/codegen/src/java/com/amd/aparapi/test/If_While_Else_While.java
new file mode 100644
index 00000000..368533d4
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/If_While_Else_While.java
@@ -0,0 +1,46 @@
+package com.amd.aparapi.test;
+
+public class If_While_Else_While{
+   public void run() {
+      boolean a = true;
+
+      if (a) {
+         while (a) {
+            a = false;
+         }
+      } else {
+         while (!a) {
+            a = true;
+         }
+      }
+
+   }
+}
+/**{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 a = 1;
+      if (a!=0){
+         for (; a!=0; a = 0){
+         }
+      } else {
+         for (; a==0; a = 1){
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ImplementsInterface.java b/test/codegen/src/java/com/amd/aparapi/test/ImplementsInterface.java
new file mode 100644
index 00000000..8905b303
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ImplementsInterface.java
@@ -0,0 +1,52 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+interface IFoo{
+   public int bar(int n);
+}
+
+public class ImplementsInterface extends Kernel implements IFoo{
+   int out[] = new int[1];
+
+   int ival = 3;
+
+   public int bar(int n) {
+      return n + ival;
+   }
+
+   public void run() {
+      out[0] = bar(1);
+      @SuppressWarnings("unused") boolean pass = false;
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   int ival;
+   __global int *out;   
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+int com_amd_aparapi_test_ImplementsInterface__bar(This *this, int n){
+   return((n + this->ival));
+}
+__kernel void run(
+   int ival, 
+   __global int *out,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->ival = ival;
+   this->out = out;
+   this->passid = passid;
+   {
+      this->out[0]  = com_amd_aparapi_test_ImplementsInterface__bar(this, 1);
+      char pass = 0;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IncArrayArgContent.java b/test/codegen/src/java/com/amd/aparapi/test/IncArrayArgContent.java
new file mode 100644
index 00000000..2794b344
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IncArrayArgContent.java
@@ -0,0 +1,43 @@
+package com.amd.aparapi.test;
+
+public class IncArrayArgContent{
+
+   int arr[] = new int[10];
+
+   public void run() {
+
+      incit(arr);
+   }
+
+   public void incit(int[] arr) {
+      arr[0]++;
+
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *arr;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+void com_amd_aparapi_test_IncArrayArgContent__incit(This *this,  __global int* arr){
+   arr[0]  = arr[0] + 1;
+   return;
+}
+__kernel void run(
+   __global int *arr,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->arr = arr;
+   this->passid = passid;
+   {
+      com_amd_aparapi_test_IncArrayArgContent__incit(this, this->arr);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IncField.java b/test/codegen/src/java/com/amd/aparapi/test/IncField.java
new file mode 100644
index 00000000..8f4a4e11
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IncField.java
@@ -0,0 +1,10 @@
+package com.amd.aparapi.test;
+
+public class IncField{
+   int field = 1024;
+
+   public void run() {
+      field++;
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/IndirectRecursion.java b/test/codegen/src/java/com/amd/aparapi/test/IndirectRecursion.java
new file mode 100644
index 00000000..61a2fd61
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/IndirectRecursion.java
@@ -0,0 +1,26 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class IndirectRecursion extends Kernel{
+
+   public void run() {
+      intout[0] = foo(10);
+      @SuppressWarnings("unused") boolean pass = false;
+   }
+
+   int foo(int n) {
+      if (n > 0) {
+         return bar(n);
+      }
+      return -1;
+   }
+
+   int bar(int n) {
+      return foo(--n);
+   }
+
+   int intout[] = new int[1];
+
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/Interface.java b/test/codegen/src/java/com/amd/aparapi/test/Interface.java
new file mode 100644
index 00000000..ee242847
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/Interface.java
@@ -0,0 +1,23 @@
+package com.amd.aparapi.test;
+
+public class Interface{
+
+   public interface Operator{
+      public double operate(double d);
+   }
+
+   public class SimpleAdder implements Operator{
+      public double operate(double d) {
+         return d + 1.0;
+      }
+   }
+
+   public void run() {
+      out[0] = sa.operate(0.0);
+   }
+
+   double out[] = new double[1];
+
+   Operator sa = new SimpleAdder();
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/LongCompare.java b/test/codegen/src/java/com/amd/aparapi/test/LongCompare.java
new file mode 100644
index 00000000..7466da31
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/LongCompare.java
@@ -0,0 +1,40 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class LongCompare extends Kernel{
+   public void run() {
+      long n1 = 1;
+      long n2 = 2;
+      @SuppressWarnings("unused") boolean pass = false;
+      if (n2 > n1)
+         pass = true;
+   }
+}
+/**{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;
+   {
+      long n1 = 1L;
+      long n2 = 2L;
+      char pass = 0;
+      if ((n2 - n1)>0){
+         pass = 1;
+      }
+      return;
+   }
+}
+
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/LongCompares.java b/test/codegen/src/java/com/amd/aparapi/test/LongCompares.java
new file mode 100644
index 00000000..d9d5c2bd
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/LongCompares.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class LongCompares{
+   public void run() {
+
+      @SuppressWarnings("unused") boolean pass = false;
+      long l1 = 1L;
+      long l2 = 1L;
+      if (l1 > l2) {
+         pass = true;
+      }
+
+   }
+}
+/**{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;
+      long l1 = 1L;
+      long l2 = 1L;
+      if ((l1 - l2)>0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/Loops.java b/test/codegen/src/java/com/amd/aparapi/test/Loops.java
new file mode 100644
index 00000000..02bc06bb
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/Loops.java
@@ -0,0 +1,41 @@
+package com.amd.aparapi.test;
+
+public class Loops{
+   public void run() {
+      int sum = 0;
+
+      for (int i = 0; i < 100; i++) {
+         sum = sum + ++i;
+      }
+
+      for (int i = 0; i < 100; i++) {
+         sum = sum + i++;
+      }
+   }
+}
+/**{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;
+      {
+         int sum = 0;
+         for (int i = 0; i<100; i++){
+            sum = sum + ++i;
+         }
+         for (int i = 0; i<100; i++){
+            sum = sum + i++;
+         }
+         return;
+      }
+   }
+}OpenCL}**/
+
diff --git a/test/codegen/src/java/com/amd/aparapi/test/MathAbs.java b/test/codegen/src/java/com/amd/aparapi/test/MathAbs.java
new file mode 100644
index 00000000..d0f6b264
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/MathAbs.java
@@ -0,0 +1,45 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class MathAbs extends Kernel{
+   public void run() {
+      double d = -1.0;
+      float f = -1.0f;
+      int i = -1;
+      long n = -1;
+      @SuppressWarnings("unused") boolean pass = true;
+      if ((abs(d) != 1) || (abs(f) != 1) || (abs(i) != 1) || (abs(n) != 1))
+         pass = false;
+   }
+}
+/**{OpenCL{
+#pragma OPENCL EXTENSION cl_amd_fp64 : enable
+
+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;
+   {
+      double d = -1.0;
+      float f = -1.0f;
+      int i = -1;
+      long n = -1L;
+      char pass = 1;
+      if (fabs(d)!=1.0 || fabs(f)!=1.0f || abs(i)!=1 || (abs(n) - 1L)!=0){
+         pass = 0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/MathDegRad.java b/test/codegen/src/java/com/amd/aparapi/test/MathDegRad.java
new file mode 100644
index 00000000..1844d408
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/MathDegRad.java
@@ -0,0 +1,41 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class MathDegRad extends Kernel{
+   public void run() {
+      double d = -1.0;
+      float f = -1.0f;
+      @SuppressWarnings("unused") boolean pass = true;
+      if ((toRadians(toDegrees(d)) != d) || (toRadians(toDegrees(f)) != f))
+         pass = false;
+   }
+}
+/**{OpenCL{
+#pragma OPENCL EXTENSION cl_amd_fp64 : enable
+
+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;
+   {
+      double d = -1.0;
+      float f = -1.0f;
+      char pass = 1;
+      if (radians(degrees(d))!=d || radians(degrees(f))!=f){
+         pass = 0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/MathFallThru.java b/test/codegen/src/java/com/amd/aparapi/test/MathFallThru.java
new file mode 100644
index 00000000..5e286c24
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/MathFallThru.java
@@ -0,0 +1,51 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class MathFallThru extends Kernel{
+
+   public void run() {
+      float f1 = 1.0f;
+      double d1 = 1.0;
+      longout[0] = round(ceil(cos(exp(floor(log(pow(d1, d1)))))) + tan(sqrt(sin(rint(acos(asin(atan(atan2(d1, d1)))))))));
+      intout[0] = round(ceil(cos(exp(floor(log(pow(f1, f1)))))) + tan(sqrt(sin(rint(acos(asin(atan(atan2(f1, f1)))))))));
+      @SuppressWarnings("unused") boolean pass = false;
+   }
+
+   long longout[] = new long[1];
+
+   int intout[] = new int[1];
+}
+/**{OpenCL{
+#pragma OPENCL EXTENSION cl_amd_fp64 : enable
+
+typedef struct This_s{
+   __global long *longout;
+   __global int *intout;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global long *longout,
+   __global int *intout,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->longout = longout;
+   this->intout = intout;
+   this->passid = passid;
+   {
+      float f1 = 1.0f;
+      double d1 = 1.0;
+      this->longout[0]  = round((ceil(cos(exp(floor(log(pow(d1, d1)))))) + tan(sqrt(sin(rint(acos(asin(atan(atan2(d1, d1))))))))));
+      this->intout[0]  = round((ceil(cos(exp(floor(log(pow(f1, f1)))))) + tan(sqrt(sin(rint(acos(asin(atan(atan2(f1, f1))))))))));
+      char pass = 0;
+      return;
+   }
+}
+
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/MathMax.java b/test/codegen/src/java/com/amd/aparapi/test/MathMax.java
new file mode 100644
index 00000000..1d7e0913
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/MathMax.java
@@ -0,0 +1,50 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class MathMax extends Kernel{
+   public void run() {
+      double d1 = -1.0, d2 = 1.0;
+      float f1 = -1.0f, f2 = 1.0f;
+      int i1 = -1, i2 = 1;
+      long n1 = -1, n2 = 1;
+      @SuppressWarnings("unused") boolean pass = true;
+      if ((max(d1, d2) != 1) || (max(f1, f2) != 1) || (max(i1, i2) != 1) || (max(n1, n2) != 1))
+         pass = false;
+   }
+}
+/**{OpenCL{
+#pragma OPENCL EXTENSION cl_amd_fp64 : enable
+
+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;
+   {
+      double d1 = -1.0;
+      double d2 = 1.0;
+      float f1 = -1.0f;
+      float f2 = 1.0f;
+      int i1 = -1;
+      int i2 = 1;
+      long n1 = -1L;
+      long n2 = 1L;
+      char pass = 1;
+      if (fmax(d1, d2)!=1.0 || fmax(f1, f2)!=1.0f || max(i1, i2)!=1 || (max(n1, n2) - 1L)!=0){
+         pass = 0;
+      }
+      return;
+   }
+}
+
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/MathMin.java b/test/codegen/src/java/com/amd/aparapi/test/MathMin.java
new file mode 100644
index 00000000..7544613c
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/MathMin.java
@@ -0,0 +1,50 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class MathMin extends Kernel{
+   public void run() {
+      double d1 = -1.0, d2 = 1.0;
+      float f1 = -1.0f, f2 = 1.0f;
+      int i1 = -1, i2 = 1;
+      long n1 = -1, n2 = 1;
+      @SuppressWarnings("unused") boolean pass = true;
+      if ((min(d1, d2) != 1) || (min(f1, f2) != 1) || (min(i1, i2) != 1) || (min(n1, n2) != 1))
+         pass = false;
+   }
+}
+/**{OpenCL{
+#pragma OPENCL EXTENSION cl_amd_fp64 : enable
+
+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;
+   {
+      double d1 = -1.0;
+      double d2 = 1.0;
+      float f1 = -1.0f;
+      float f2 = 1.0f;
+      int i1 = -1;
+      int i2 = 1;
+      long n1 = -1L;
+      long n2 = 1L;
+      char pass = 1;
+      if (fmin(d1, d2)!=1.0 || fmin(f1, f2)!=1.0f || min(i1, i2)!=1 || (min(n1, n2) - 1L)!=0){
+         pass = 0;
+      }
+      return;
+   }
+}
+
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/MathRemainder.java b/test/codegen/src/java/com/amd/aparapi/test/MathRemainder.java
new file mode 100644
index 00000000..1a5cb2a0
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/MathRemainder.java
@@ -0,0 +1,43 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class MathRemainder extends Kernel{
+   public void run() {
+      double d1 = 7.0, d2 = 2.0;
+      float f1 = 7.0f, f2 = 2.0f;
+      @SuppressWarnings("unused") boolean pass = true;
+      if ((IEEEremainder(d1, d2) != 1) || (IEEEremainder(f1, f2) != 1))
+         pass = false;
+   }
+}
+/**{OpenCL{
+#pragma OPENCL EXTENSION cl_amd_fp64 : enable
+
+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;
+   {
+      double d1 = 7.0;
+      double d2 = 2.0;
+      float f1 = 7.0f;
+      float f2 = 2.0f;
+      char pass = 1;
+      if (remainder(d1, d2)!=1.0 || remainder(f1, f2)!=1.0f){
+         pass = 0;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/MultiContinue.java b/test/codegen/src/java/com/amd/aparapi/test/MultiContinue.java
new file mode 100644
index 00000000..dfb00d14
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/MultiContinue.java
@@ -0,0 +1,59 @@
+package com.amd.aparapi.test;
+
+public class MultiContinue{
+   public void run() {
+      @SuppressWarnings("unused") boolean pass = false;
+      for (int i = 0; i < 10; i++) {
+         if (i == 5) {
+            continue;
+         } else {
+            if (i == 2) {
+               continue;
+            }
+            if (i == 1) {
+               continue;
+            }
+         }
+         if (i == 10) {
+            continue;
+         }
+         pass = true;
+      }
+   }
+}
+/**{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;
+      for (int i = 0; i<10; i++){
+         if (i==5){
+         } else {
+            if (i==2){
+            } else {
+               if (i==1){
+               } else {
+                  if (i==10){
+                  } else {
+                     pass = 1;
+                  }
+               }
+            }
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/MultipleAssign.java b/test/codegen/src/java/com/amd/aparapi/test/MultipleAssign.java
new file mode 100644
index 00000000..54e762ec
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/MultipleAssign.java
@@ -0,0 +1,36 @@
+package com.amd.aparapi.test;
+
+public class MultipleAssign{
+
+   public void run() {
+      @SuppressWarnings("unused") int a = 0;
+      @SuppressWarnings("unused") int b = 0;
+      @SuppressWarnings("unused") int c = 0;
+      a = b = c = 4;
+
+   }
+}
+/**{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;
+   {
+      int a = 0;
+      int b = 0;
+      int c = 0;
+      a = b = c = 4;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/MultipleAssignExpr.java b/test/codegen/src/java/com/amd/aparapi/test/MultipleAssignExpr.java
new file mode 100644
index 00000000..758ebfc0
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/MultipleAssignExpr.java
@@ -0,0 +1,43 @@
+package com.amd.aparapi.test;
+
+public class MultipleAssignExpr{
+
+   int sum(int lhs, int rhs) {
+      return (lhs + rhs);
+   }
+
+   public void run() {
+      @SuppressWarnings("unused") int a = 0;
+      @SuppressWarnings("unused") int b = 0;
+      @SuppressWarnings("unused") int c = 0;
+      a = b = c = sum(1, 2);
+
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+int com_amd_aparapi_test_MultipleAssignExpr__sum(This *this, int lhs, int rhs){
+   return((lhs + rhs));
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      int a = 0;
+      int b = 0;
+      int c = 0;
+      a = b = c = com_amd_aparapi_test_MultipleAssignExpr__sum(this, 1, 2);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/NewLocalArray.java b/test/codegen/src/java/com/amd/aparapi/test/NewLocalArray.java
new file mode 100644
index 00000000..d8567efa
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/NewLocalArray.java
@@ -0,0 +1,39 @@
+package com.amd.aparapi.test;
+
+public class NewLocalArray{
+
+   int array[] = new int[4];
+
+   public void run() {
+      @SuppressWarnings("unused") boolean pass = false;
+      int i = 0;
+      if (i++ == 0)
+         pass = true;
+
+   }
+}
+/**{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;
+      if (i++==0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayCallHierarchy.java b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayCallHierarchy.java
new file mode 100644
index 00000000..2cd587ca
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayCallHierarchy.java
@@ -0,0 +1,68 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class ObjectArrayCallHierarchy extends Kernel{
+
+   final static int size = 16;
+
+   static class DummyParent{
+      int intField;
+
+      int field2;
+
+      public DummyParent() {
+         intField = -3;
+         field2 = -4;
+      }
+
+      public int getIntField() {
+         return intField;
+      }
+
+      public void setIntField(int x) {
+         intField = x;
+      }
+
+      public void call2() {
+         setIntField(intField + field2);
+      }
+
+   };
+
+   final static class DummyOOA extends DummyParent{
+      int intField;
+
+      public void funnyCall() {
+         setIntField(intField + getIntField());
+         call2();
+      }
+
+      public int funnyGet() {
+         funnyCall();
+         setIntField(intField + getIntField());
+         return intField + getIntField();
+      }
+   };
+
+   int something;
+
+   DummyOOA dummy[] = null;
+
+   public ObjectArrayCallHierarchy() {
+      something = -1;
+      dummy = new DummyOOA[size];
+      dummy[0] = new DummyOOA();
+   }
+
+   public int bar(int x) {
+      return -x;
+   }
+
+   public void run() {
+      int myId = getGlobalId();
+      dummy[myId].intField = bar(2) + dummy[myId].funnyGet();
+   }
+}
+
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayCommonSuper.java b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayCommonSuper.java
new file mode 100644
index 00000000..9fef5b8b
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayCommonSuper.java
@@ -0,0 +1,53 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class ObjectArrayCommonSuper extends Kernel{
+
+   final static int size = 16;
+
+   static class DummyParent{
+      int intField;
+
+      public DummyParent() {
+         intField = -3;
+      }
+
+      public int getIntField() {
+         return intField;
+      }
+   };
+
+   final static class DummyBrother extends DummyParent{
+      int brosInt;
+
+      public int getBrosInt() {
+         return brosInt;
+      }
+   };
+
+   final static class DummySister extends DummyParent{
+      int sisInt;
+
+      public int getSisInt() {
+         return sisInt;
+      }
+   };
+
+   DummyBrother db[] = new DummyBrother[size];
+
+   DummySister ds[] = new DummySister[size];
+
+   public ObjectArrayCommonSuper() {
+      db[0] = new DummyBrother();
+      ds[0] = new DummySister();
+   }
+
+   public void run() {
+      int myId = getGlobalId();
+      db[myId].intField = db[myId].getIntField() + db[myId].getBrosInt();
+      ds[myId].intField = ds[myId].getIntField() + ds[myId].getSisInt();
+   }
+}
+
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberAccess.java b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberAccess.java
new file mode 100644
index 00000000..b721968c
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberAccess.java
@@ -0,0 +1,95 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class ObjectArrayMemberAccess extends Kernel{
+
+   final static class DummyOOA{
+      int mem;
+
+      float floatField;
+
+      public DummyOOA() {
+         mem = -3;
+         floatField = -3;
+      }
+
+      public int getMem() {
+         return mem;
+      }
+
+      public void setMem(int x) {
+         mem = x;
+      }
+
+      public float getFloatField() {
+         return floatField;
+      }
+
+      public void setFloatField(float x) {
+         floatField = x;
+      }
+
+   };
+
+   int out[] = new int[2];
+
+   int something;
+
+   DummyOOA dummy[] = null;
+
+   final int size = 64;
+
+   public ObjectArrayMemberAccess() {
+      something = -1;
+      dummy = new DummyOOA[size];
+
+      dummy[0] = new DummyOOA();
+   }
+
+   public int getSomething() {
+      return something;
+   }
+
+   public int bar(int x) {
+      return -x;
+   }
+
+   public void run() {
+      int myId = getGlobalId();
+      dummy[myId].mem = dummy[myId].mem + 2;
+      dummy[myId].floatField = dummy[myId].floatField + (float) 2.0;
+   }
+}
+
+/**{OpenCL{
+typedef struct com_amd_aparapi_test_ObjectArrayMemberAccess$DummyOOA_s{
+   int  mem;
+   float  floatField;
+   
+} com_amd_aparapi_test_ObjectArrayMemberAccess$DummyOOA;
+
+typedef struct This_s{
+   __global com_amd_aparapi_test_ObjectArrayMemberAccess$DummyOOA *dummy;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global com_amd_aparapi_test_ObjectArrayMemberAccess$DummyOOA *dummy,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->dummy = dummy;
+   this->passid = passid;
+   {
+      int myId = get_global_id(0);
+      this->dummy[myId].mem=this->dummy[myId].mem + 2;
+      this->dummy[myId].floatField=this->dummy[myId].floatField + 2.0f;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberBadGetter.java b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberBadGetter.java
new file mode 100644
index 00000000..b2225787
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberBadGetter.java
@@ -0,0 +1,40 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class ObjectArrayMemberBadGetter extends Kernel{
+
+   final class DummyOOA{
+      int mem;
+
+      float floatField;
+
+      float theOtherFloatField;
+
+      public float getFloatField() {
+         //return floatField;
+         return theOtherFloatField;
+      }
+
+      public void setFloatField(float x) {
+         floatField = x;
+      }
+   };
+
+   DummyOOA dummy[] = null;
+
+   final int size = 64;
+
+   public ObjectArrayMemberBadGetter() {
+      dummy = new DummyOOA[size];
+
+      dummy[0] = new DummyOOA();
+   }
+
+   public void run() {
+      int myId = getGlobalId();
+      dummy[myId].setFloatField(dummy[myId].getFloatField() + (float) 2.0);
+   }
+}
+
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberBadSetter.java b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberBadSetter.java
new file mode 100644
index 00000000..b8da86a9
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberBadSetter.java
@@ -0,0 +1,39 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class ObjectArrayMemberBadSetter extends Kernel{
+
+   final class DummyOOA{
+      int mem;
+
+      float floatField;
+
+      float theOtherFloatField;
+
+      public float getFloatField() {
+         return floatField;
+      }
+
+      public void setFloatField(float x) {
+         theOtherFloatField = x;
+      }
+   };
+
+   DummyOOA dummy[] = null;
+
+   final int size = 64;
+
+   public ObjectArrayMemberBadSetter() {
+      dummy = new DummyOOA[size];
+
+      dummy[0] = new DummyOOA();
+   }
+
+   public void run() {
+      int myId = getGlobalId();
+      dummy[myId].setFloatField(dummy[myId].getFloatField() + (float) 2.0);
+   }
+}
+
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberCall.java b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberCall.java
new file mode 100644
index 00000000..ef558902
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberCall.java
@@ -0,0 +1,108 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class ObjectArrayMemberCall extends Kernel{
+
+   final static class DummyOOA{
+      int mem;
+
+      public DummyOOA() {
+         mem = -3;
+      }
+
+      public int getMem() {
+         return mem;
+      }
+
+      public void setMem(int x) {
+         mem = x;
+      }
+
+      public int addEmUp(int x, int y) {
+         return x + y;
+      }
+
+      public int addToMem(int x) {
+         return x + mem;
+      }
+
+      public int addEmUpPlusOne(int x, int y) {
+         return addEmUp(x, y) + 1 + getMem();
+      }
+   };
+
+   int out[] = new int[2];
+
+   int something;
+
+   DummyOOA dummy[] = null;
+
+   final int size = 64;
+
+   public ObjectArrayMemberCall() {
+      something = -1;
+      dummy = new DummyOOA[size];
+
+      dummy[0] = new DummyOOA();
+   }
+
+   public int getSomething() {
+      return something;
+   }
+
+   public int bar(int x) {
+      return -x;
+   }
+
+   public void run() {
+      int myId = getGlobalId();
+      dummy[myId].mem = dummy[myId].addEmUp(dummy[myId].mem, 2);
+      int tmp = dummy[myId].addToMem(2);
+      int tmp2 = dummy[myId].addEmUpPlusOne(2, tmp);
+   }
+}
+
+/**{OpenCL{
+typedef struct com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA_s{
+   int  mem;
+   
+} com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA;
+
+typedef struct This_s{
+   __global com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA *dummy;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+int com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA__getMem( __global com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA *this){
+   return(this->mem);
+}
+int com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA__addEmUp( __global com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA *this, int x, int y){
+   return((x + y));
+}
+int com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA__addEmUpPlusOne( __global com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA *this, int x, int y){
+   return(((com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA__addEmUp(this, x, y) + 1) + com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA__getMem(this)));
+}
+int com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA__addToMem( __global com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA *this, int x){
+   return((x + this->mem));
+}
+__kernel void run(
+   __global com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA *dummy,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->dummy = dummy;
+   this->passid = passid;
+   {
+      int myId = get_global_id(0);
+      this->dummy[myId].mem=com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA__addEmUp( &(this->dummy[myId]), this->dummy[myId].mem, 2);
+      int tmp = com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA__addToMem( &(this->dummy[myId]), 2);
+      int tmp2 = com_amd_aparapi_test_ObjectArrayMemberCall$DummyOOA__addEmUpPlusOne( &(this->dummy[myId]), 2, tmp);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberGetterSetter.java b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberGetterSetter.java
new file mode 100644
index 00000000..b48fdd42
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberGetterSetter.java
@@ -0,0 +1,223 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+final class DummyOOA{
+   int mem;
+
+   float floatField;
+
+   long longField;
+
+   boolean boolField;
+
+   byte byteField;
+
+   public DummyOOA() {
+      mem = 8;
+   }
+
+   public boolean isBoolField() {
+      return boolField;
+   }
+
+   public boolean getBoolField() {
+      return boolField;
+   }
+
+   public void setBoolField(boolean x) {
+      //boolField = x & true;
+      boolField = x;
+   }
+
+   public int getMem() {
+      return mem;
+   }
+
+   public void setMem(int x) {
+      mem = x;
+   }
+
+   public float getFloatField() {
+      return floatField;
+   }
+
+   public void setFloatField(float x) {
+      floatField = x;
+   }
+
+   public long getLongField() {
+      return longField;
+   }
+
+   public void setLongField(long x) {
+      longField = x;
+   }
+};
+
+final class TheOtherOne{
+   int mem;
+
+   public TheOtherOne() {
+      mem = 8;
+   }
+
+   public int getMem() {
+      return mem;
+   }
+
+   public void setMem(int x) {
+      mem = x;
+   }
+};
+
+public class ObjectArrayMemberGetterSetter extends Kernel{
+
+   int out[] = new int[2];
+
+   int something;
+
+   DummyOOA dummy[] = null;
+
+   TheOtherOne other[] = null;
+
+   final int size = 64;
+
+   public ObjectArrayMemberGetterSetter() {
+      something = -1;
+      dummy = new DummyOOA[size];
+      other = new TheOtherOne[size];
+
+      dummy[0] = new DummyOOA();
+      other[0] = new TheOtherOne();
+   }
+
+   public int getSomething() {
+      return something;
+   }
+
+   public int bar(int x) {
+      return -x;
+   }
+
+   public void run() {
+      int myId = getGlobalId();
+
+      int tmp = dummy[myId].getMem();
+
+      dummy[myId].setMem(dummy[myId].getMem() + 2);
+
+      dummy[myId].setMem(other[myId].getMem() + getSomething());
+
+      other[myId].setMem(other[myId].getMem() + getSomething());
+
+      dummy[myId].setLongField(dummy[myId].getLongField() + 2);
+
+      dummy[myId].setFloatField(dummy[myId].getFloatField() + (float) 2.0);
+
+      dummy[myId].setBoolField(dummy[myId].getBoolField() | dummy[myId].isBoolField());
+
+      out[myId] = getSomething();
+   }
+}
+/**{OpenCL{
+typedef struct com_amd_aparapi_test_TheOtherOne_s{
+   int  mem;
+   
+} com_amd_aparapi_test_TheOtherOne;
+
+typedef struct com_amd_aparapi_test_DummyOOA_s{
+   long  longField;
+   float  floatField;
+   int  mem;
+   char  boolField;
+   char _pad_17;
+   char _pad_18;
+   char _pad_19;
+   char _pad_20;
+   char _pad_21;
+   char _pad_22;
+   char _pad_23;
+   
+} com_amd_aparapi_test_DummyOOA;
+
+typedef struct This_s{
+   int something;
+   __global com_amd_aparapi_test_DummyOOA *dummy;
+   __global com_amd_aparapi_test_TheOtherOne *other;
+   __global int *out;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+void com_amd_aparapi_test_DummyOOA__setBoolField( __global com_amd_aparapi_test_DummyOOA *this, char x){
+   this->boolField=x;
+   return;
+}
+char com_amd_aparapi_test_DummyOOA__isBoolField( __global com_amd_aparapi_test_DummyOOA *this){
+   return(this->boolField);
+}
+char com_amd_aparapi_test_DummyOOA__getBoolField( __global com_amd_aparapi_test_DummyOOA *this){
+   return(this->boolField);
+}
+void com_amd_aparapi_test_DummyOOA__setFloatField( __global com_amd_aparapi_test_DummyOOA *this, float x){
+   this->floatField=x;
+   return;
+}
+float com_amd_aparapi_test_DummyOOA__getFloatField( __global com_amd_aparapi_test_DummyOOA *this){
+   return(this->floatField);
+}
+void com_amd_aparapi_test_DummyOOA__setLongField( __global com_amd_aparapi_test_DummyOOA *this, long x){
+   this->longField=x;
+   return;
+}
+long com_amd_aparapi_test_DummyOOA__getLongField( __global com_amd_aparapi_test_DummyOOA *this){
+   return(this->longField);
+}
+void com_amd_aparapi_test_TheOtherOne__setMem( __global com_amd_aparapi_test_TheOtherOne *this, int x){
+   this->mem=x;
+   return;
+}
+int com_amd_aparapi_test_ObjectArrayMemberGetterSetter__getSomething(This *this){
+   return(this->something);
+}
+int com_amd_aparapi_test_TheOtherOne__getMem( __global com_amd_aparapi_test_TheOtherOne *this){
+   return(this->mem);
+}
+void com_amd_aparapi_test_DummyOOA__setMem( __global com_amd_aparapi_test_DummyOOA *this, int x){
+   this->mem=x;
+   return;
+}
+int com_amd_aparapi_test_DummyOOA__getMem( __global com_amd_aparapi_test_DummyOOA *this){
+   return(this->mem);
+}
+__kernel void run(
+   int something, 
+   __global com_amd_aparapi_test_DummyOOA *dummy, 
+   __global com_amd_aparapi_test_TheOtherOne *other, 
+   __global int *out,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->something = something;
+   this->dummy = dummy;
+   this->other = other;
+   this->out = out;
+   this->passid = passid;
+   {
+      int myId = get_global_id(0);
+      int tmp = com_amd_aparapi_test_DummyOOA__getMem( &(this->dummy[myId]));
+      com_amd_aparapi_test_DummyOOA__setMem( &(this->dummy[myId]), (com_amd_aparapi_test_DummyOOA__getMem( &(this->dummy[myId])) + 2));
+      com_amd_aparapi_test_DummyOOA__setMem( &(this->dummy[myId]), (com_amd_aparapi_test_TheOtherOne__getMem( &(this->other[myId])) + com_amd_aparapi_test_ObjectArrayMemberGetterSetter__getSomething(this)));
+      com_amd_aparapi_test_TheOtherOne__setMem( &(this->other[myId]), (com_amd_aparapi_test_TheOtherOne__getMem( &(this->other[myId])) + com_amd_aparapi_test_ObjectArrayMemberGetterSetter__getSomething(this)));
+      com_amd_aparapi_test_DummyOOA__setLongField( &(this->dummy[myId]), (com_amd_aparapi_test_DummyOOA__getLongField( &(this->dummy[myId])) + 2L));
+      com_amd_aparapi_test_DummyOOA__setFloatField( &(this->dummy[myId]), (com_amd_aparapi_test_DummyOOA__getFloatField( &(this->dummy[myId])) + 2.0f));
+      com_amd_aparapi_test_DummyOOA__setBoolField( &(this->dummy[myId]), (com_amd_aparapi_test_DummyOOA__getBoolField( &(this->dummy[myId])) | com_amd_aparapi_test_DummyOOA__isBoolField( &(this->dummy[myId]))));
+      this->out[myId]  = com_amd_aparapi_test_ObjectArrayMemberGetterSetter__getSomething(this);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberHierarchy.java b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberHierarchy.java
new file mode 100644
index 00000000..b8cb163b
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberHierarchy.java
@@ -0,0 +1,111 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class ObjectArrayMemberHierarchy extends Kernel{
+
+   final static int size = 16;
+
+   static class DummyParent{
+      int intField;
+
+      public DummyParent() {
+         intField = -3;
+      }
+
+      public int getIntField() {
+         return intField;
+      }
+
+      public void setIntField(int x) {
+         intField = x;
+      }
+
+      public int foo() {
+         return 42 + getIntField();
+      }
+
+   };
+
+   final static class DummyOOA extends DummyParent{
+      float floatField;
+
+      public float getFloatField() {
+         return floatField;
+      }
+
+      public void setFloatField(float x) {
+         floatField = x;
+      }
+   };
+
+   int something;
+
+   DummyOOA dummy[] = null;
+
+   public ObjectArrayMemberHierarchy() {
+      something = -1;
+      dummy = new DummyOOA[size];
+
+      dummy[0] = new DummyOOA();
+   }
+
+   public int getSomething() {
+      return something;
+   }
+
+   public int bar(int x) {
+      return -x;
+   }
+
+   public void run() {
+      int myId = getGlobalId();
+      dummy[myId].intField = dummy[myId].getIntField() + 2 + getSomething();
+      dummy[myId].setFloatField(dummy[myId].floatField + (float) 2.0);
+   }
+}
+
+/**{OpenCL{
+typedef struct com_amd_aparapi_test_ObjectArrayMemberHierarchy$DummyOOA_s{
+   float  floatField;
+   int  intField;
+   
+} com_amd_aparapi_test_ObjectArrayMemberHierarchy$DummyOOA;
+
+typedef struct This_s{
+   int something;
+   __global com_amd_aparapi_test_ObjectArrayMemberHierarchy$DummyOOA *dummy;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+void com_amd_aparapi_test_ObjectArrayMemberHierarchy$DummyOOA__setFloatField( __global com_amd_aparapi_test_ObjectArrayMemberHierarchy$DummyOOA *this, float x){
+   this->floatField=x;
+   return;
+}
+int com_amd_aparapi_test_ObjectArrayMemberHierarchy__getSomething(This *this){
+   return(this->something);
+}
+int com_amd_aparapi_test_ObjectArrayMemberHierarchy$DummyParent__getIntField( __global com_amd_aparapi_test_ObjectArrayMemberHierarchy$DummyOOA *this){
+   return(this->intField);
+}
+__kernel void run(
+   int something, 
+   __global com_amd_aparapi_test_ObjectArrayMemberHierarchy$DummyOOA *dummy,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->something = something;
+   this->dummy = dummy;
+   this->passid = passid;
+   {
+      int myId = get_global_id(0);
+      this->dummy[myId].intField=(com_amd_aparapi_test_ObjectArrayMemberHierarchy$DummyParent__getIntField( &(this->dummy[myId])) + 2) + com_amd_aparapi_test_ObjectArrayMemberHierarchy__getSomething(this);
+      com_amd_aparapi_test_ObjectArrayMemberHierarchy$DummyOOA__setFloatField( &(this->dummy[myId]), (this->dummy[myId].floatField + 2.0f));
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberNotFinal.java b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberNotFinal.java
new file mode 100644
index 00000000..bcc0621d
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ObjectArrayMemberNotFinal.java
@@ -0,0 +1,91 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+class DummyOOANF{
+   int mem;
+
+   float floatField;
+
+   long longField;
+
+   boolean boolField;
+
+   byte byteField;
+
+   public DummyOOANF() {
+      mem = 8;
+   }
+
+   public boolean isBoolField() {
+      return boolField;
+   }
+
+   public boolean getBoolField() {
+      return boolField;
+   }
+
+   public void setBoolField(boolean x) {
+      //boolField = x & true;
+      boolField = x;
+   }
+
+   public int getMem() {
+      return mem;
+   }
+
+   public void setMem(int x) {
+      mem = x;
+   }
+
+   public float getFloatField() {
+      return floatField;
+   }
+
+   public void setFloatField(float x) {
+      floatField = x;
+   }
+
+   public long getLongField() {
+      return longField;
+   }
+
+   public void setLongField(long x) {
+      longField = x;
+   }
+};
+
+public class ObjectArrayMemberNotFinal extends Kernel{
+
+   int out[] = new int[2];
+
+   int something;
+
+   DummyOOANF dummy[] = null;
+
+   final int size = 64;
+
+   public ObjectArrayMemberNotFinal() {
+      something = -1;
+      dummy = new DummyOOANF[size];
+
+      dummy[0] = new DummyOOANF();
+   }
+
+   public int getSomething() {
+      return something;
+   }
+
+   public int bar(int x) {
+      return -x;
+   }
+
+   public void run() {
+      int myId = getGlobalId();
+
+      int tmp = dummy[myId].getMem();
+
+      dummy[myId].setMem(dummy[myId].getMem() + 2);
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ObjectRefCopy.java b/test/codegen/src/java/com/amd/aparapi/test/ObjectRefCopy.java
new file mode 100644
index 00000000..1163b091
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ObjectRefCopy.java
@@ -0,0 +1,23 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class ObjectRefCopy extends Kernel{
+
+   final static class DummyOOA{
+      int mem;
+
+      float floatField;
+   };
+
+   final int size = 8;
+
+   DummyOOA dummy[] = new DummyOOA[size];
+
+   public void run() {
+      int myId = getGlobalId();
+      dummy[myId] = dummy[myId + 1];
+   }
+}
+
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ObjectWithinObject.java b/test/codegen/src/java/com/amd/aparapi/test/ObjectWithinObject.java
new file mode 100644
index 00000000..e38658b9
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ObjectWithinObject.java
@@ -0,0 +1,26 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class ObjectWithinObject extends Kernel{
+
+   final static class DummyOOA{
+      int mem;
+
+      float floatField;
+
+      DummyOOA next;
+
+   };
+
+   final int size = 8;
+
+   DummyOOA dummy[] = new DummyOOA[size];
+
+   public void run() {
+      int myId = getGlobalId();
+      dummy[myId].mem = dummy[myId].next.mem + 4;
+   }
+}
+
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/OrAndOrPrecedence.java b/test/codegen/src/java/com/amd/aparapi/test/OrAndOrPrecedence.java
new file mode 100644
index 00000000..4160bdcc
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/OrAndOrPrecedence.java
@@ -0,0 +1,44 @@
+package com.amd.aparapi.test;
+
+public class OrAndOrPrecedence{
+   public void run() {
+      boolean a = true;
+      boolean b = true;
+      boolean c = true;
+      boolean d = true;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if ((a || b) && (c || d)) {
+         pass = true;
+      }
+
+   }
+}
+/**{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 a = 1;
+      char b = 1;
+      char c = 1;
+      char d = 1;
+      char pass = 0;
+      if ((a!=0 || b!=0) && (c!=0 || d!=0)){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/OverloadMethod.java b/test/codegen/src/java/com/amd/aparapi/test/OverloadMethod.java
new file mode 100644
index 00000000..d14e275f
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/OverloadMethod.java
@@ -0,0 +1,47 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class OverloadMethod extends Kernel{
+   public void run() {
+      out[0] = foo(2) + foo(2, 3);
+   }
+
+   int foo(int n) {
+      return n + 1;
+   }
+
+   int foo(int a, int b) {
+      return min(a, b);
+   }
+
+   int out[] = new int[1];
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *out;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+int com_amd_aparapi_test_OverloadMethod__foo(This *this, int a, int b){
+   return(min(a, b));
+}
+int com_amd_aparapi_test_OverloadMethod__foo(This *this, int n){
+   return((n + 1));
+}
+__kernel void run(
+   __global int *out, 
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->out = out;
+   this->passid = passid;
+   {
+      this->out[0]  = com_amd_aparapi_test_OverloadMethod__foo(this, 2) + com_amd_aparapi_test_OverloadMethod__foo(this, 2, 3);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/OverriddenKernelField.java b/test/codegen/src/java/com/amd/aparapi/test/OverriddenKernelField.java
new file mode 100644
index 00000000..3ffec7da
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/OverriddenKernelField.java
@@ -0,0 +1,57 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+class OverriddenKernelFieldParent extends Kernel{
+   int out[] = new int[1];
+
+   int foo(int n) {
+      out[0] = n + 1;
+      return out[0];
+   }
+
+   public void run() {
+      out[0] = foo(3);
+   }
+}
+
+public class OverriddenKernelField extends OverriddenKernelFieldParent{
+   public void run() {
+      out[0] = foo(2);
+   }
+
+   int foo(int n) {
+      return super.foo(n + 1);
+   }
+
+   int out[] = new int[1];
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *out;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+int com_amd_aparapi_test_OverriddenKernelFieldParent__foo(This *this, int n){
+   this->out[0]  = n + 1;
+   return(this->out[0]);
+}
+int com_amd_aparapi_test_OverriddenKernelField__foo(This *this, int n){
+   return(com_amd_aparapi_test_OverriddenKernelFieldParent__foo(this, (n + 1)));
+}
+__kernel void run(
+   __global int *out,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->out = out;
+   this->passid = passid;
+   {
+      this->out[0]  = com_amd_aparapi_test_OverriddenKernelField__foo(this, 2);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PlayPen.java b/test/codegen/src/java/com/amd/aparapi/test/PlayPen.java
new file mode 100644
index 00000000..bf17b937
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PlayPen.java
@@ -0,0 +1,58 @@
+package com.amd.aparapi.test;
+
+public class PlayPen{
+   public void run() {
+      int testValue = 10;
+      @SuppressWarnings("unused") boolean pass = false;
+
+      if ((testValue % 2 == 0 || testValue <= 0 && (testValue >= 100) && testValue % 4 == 0)) {
+         pass = true;
+      }
+
+      if ((testValue < 3 || testValue > 5) && (testValue < 2 || testValue > 2) || testValue > 5) {
+         pass = true;
+      }
+      boolean a = false, b = false, c = false, d = false, e = false, f = false;
+      if ((a || b && c && d) && e || f) {
+         pass = true;
+      }
+
+   }
+}
+/**{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;
+   {
+      int testValue = 10;
+      char pass = 0;
+      if ((testValue % 2)==0 || testValue<=0 && testValue>=100 && (testValue % 4)==0){
+         pass = 1;
+      }
+      if ((testValue<3 || testValue>5) && (testValue<2 || testValue>2) || testValue>5){
+         pass = 1;
+      }
+      char a = 0;
+      char b = 0;
+      char c = 0;
+      char d = 0;
+      char e = 0;
+      char f = 0;
+      if ((a!=0 || b!=0 && c!=0 && d!=0) && e!=0 || f!=0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PostDecArrayItem.java b/test/codegen/src/java/com/amd/aparapi/test/PostDecArrayItem.java
new file mode 100644
index 00000000..a1414457
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PostDecArrayItem.java
@@ -0,0 +1,46 @@
+package com.amd.aparapi.test;
+
+public class PostDecArrayItem{
+
+   final static int START_SIZE = 128;
+
+   public int[] values = new int[START_SIZE];
+
+   public int[] results = new int[START_SIZE];
+
+   void actuallyDoIt(int a) {
+
+   }
+
+   public void run() {
+      int a = 10;
+      values[a] = results[a]--;
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *values;
+   __global int *results;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global int *values, 
+   __global int *results,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->values = values;
+   this->results = results;
+   this->passid = passid;
+   {
+      int a = 10;
+      this->values[a]  = this->results[a]--;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PostDecByte.java b/test/codegen/src/java/com/amd/aparapi/test/PostDecByte.java
new file mode 100644
index 00000000..078cd388
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PostDecByte.java
@@ -0,0 +1,41 @@
+package com.amd.aparapi.test;
+
+public class PostDecByte{
+
+   /**
+    * This is a nonsense test, but it should be emitted correctly to return the
+    * original value of a
+    */
+   byte incByte(byte a) {
+      return a++;
+   }
+
+   public void run() {
+      byte startValue = (byte) 3;
+      @SuppressWarnings("unused") byte result = incByte(startValue--);
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+char com_amd_aparapi_test_PostDecByte__incByte(This *this, char a){
+   return(a++);
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      char startValue = 3; 
+      char result = com_amd_aparapi_test_PostDecByte__incByte(this, startValue--);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PostDecLocal.java b/test/codegen/src/java/com/amd/aparapi/test/PostDecLocal.java
new file mode 100644
index 00000000..4e71f5a1
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PostDecLocal.java
@@ -0,0 +1,37 @@
+package com.amd.aparapi.test;
+
+public class PostDecLocal{
+
+   public void run() {
+      @SuppressWarnings("unused") boolean pass = false;
+      int i = 0;
+      if (i-- == 0)
+         pass = true;
+
+   }
+}
+/**{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;
+      if (i--==0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PostDecPostInc.java b/test/codegen/src/java/com/amd/aparapi/test/PostDecPostInc.java
new file mode 100644
index 00000000..f66a80a6
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PostDecPostInc.java
@@ -0,0 +1,34 @@
+package com.amd.aparapi.test;
+
+public class PostDecPostInc{
+
+   public void run() {
+      int i = 0;
+      @SuppressWarnings("unused") int result = 0;
+      result = i-- + i++;
+
+   }
+}
+/**{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;
+   {
+      int i = 0;
+      int result = 0;
+      result = i-- + i++;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PostIncArrayIndexAndElement.java b/test/codegen/src/java/com/amd/aparapi/test/PostIncArrayIndexAndElement.java
new file mode 100644
index 00000000..4d589226
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PostIncArrayIndexAndElement.java
@@ -0,0 +1,35 @@
+package com.amd.aparapi.test;
+
+public class PostIncArrayIndexAndElement{
+
+   int array[] = new int[4];
+
+   public void run() {
+      int i = 0;
+      array[i++]++;
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *array;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global int *array,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->array = array;
+   this->passid = passid;
+   {
+      int i = 0;
+      this->array[i++]  = this->array[i] + 1;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PostIncArrayItem.java b/test/codegen/src/java/com/amd/aparapi/test/PostIncArrayItem.java
new file mode 100644
index 00000000..7bb1abe8
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PostIncArrayItem.java
@@ -0,0 +1,46 @@
+package com.amd.aparapi.test;
+
+public class PostIncArrayItem{
+
+   final static int START_SIZE = 128;
+
+   public int[] values = new int[START_SIZE];
+
+   public int[] results = new int[START_SIZE];
+
+   void actuallyDoIt(int a) {
+
+   }
+
+   public void run() {
+      int a = 10;
+      values[a] = results[a]++;
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *values;
+   __global int *results;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global int *values, 
+   __global int *results,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->values = values;
+   this->results = results;
+   this->passid = passid;
+   {
+      int a = 10;
+      this->values[a]  = this->results[a]++;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PostIncArrayItemAsParameter.java b/test/codegen/src/java/com/amd/aparapi/test/PostIncArrayItemAsParameter.java
new file mode 100644
index 00000000..53473341
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PostIncArrayItemAsParameter.java
@@ -0,0 +1,49 @@
+package com.amd.aparapi.test;
+
+public class PostIncArrayItemAsParameter{
+
+   final static int START_SIZE = 128;
+
+   public int[] values = new int[START_SIZE];
+
+   public int[] results = new int[START_SIZE];
+
+   int actuallyDoIt(int a) {
+      return 1;
+   }
+
+   int y = 2;
+
+   public void run() {
+      actuallyDoIt(results[y]++);
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *results;
+   int y;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+int com_amd_aparapi_test_PostIncArrayItemAsParameter__actuallyDoIt(This *this, int a){
+   return(1);
+}
+__kernel void run(
+   __global int *results, 
+   int y,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->results = results;
+   this->y = y;
+   this->passid = passid;
+   {
+      com_amd_aparapi_test_PostIncArrayItemAsParameter__actuallyDoIt(this, this->results[this->y]++);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PostIncArrayItemFieldIndex.java b/test/codegen/src/java/com/amd/aparapi/test/PostIncArrayItemFieldIndex.java
new file mode 100644
index 00000000..37ed2bdf
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PostIncArrayItemFieldIndex.java
@@ -0,0 +1,45 @@
+package com.amd.aparapi.test;
+
+public class PostIncArrayItemFieldIndex{
+
+   final static int START_SIZE = 128;
+
+   public int[] values = new int[START_SIZE];
+
+   public int[] results = new int[START_SIZE];
+
+   public int a = 10;
+
+   public void run() {
+      values[a] = results[a]++;
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *values;
+   int a;
+   __global int *results;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global int *values,
+   int a,
+   __global int *results,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->values = values;
+   this->a = a;
+   this->results = results;
+   this->passid = passid;
+   {
+      this->values[this->a]  = this->results[this->a]++;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PostIncByte.java b/test/codegen/src/java/com/amd/aparapi/test/PostIncByte.java
new file mode 100644
index 00000000..130e2457
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PostIncByte.java
@@ -0,0 +1,42 @@
+package com.amd.aparapi.test;
+
+public class PostIncByte{
+
+   /**
+    * This is a nonsense test, but it should be emitted correctly to return the
+    * original value of a
+    */
+   byte incByte(byte a) {
+      return a++;
+   }
+
+   public void run() {
+      byte startValue = (byte) 3;
+      @SuppressWarnings("unused") byte result = incByte(startValue++);
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+char com_amd_aparapi_test_PostIncByte__incByte(This *this, char a){
+   return(a++);
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      char startValue = 3; 
+      char result = com_amd_aparapi_test_PostIncByte__incByte(this, startValue++);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PostIncByteField.java b/test/codegen/src/java/com/amd/aparapi/test/PostIncByteField.java
new file mode 100644
index 00000000..729256f1
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PostIncByteField.java
@@ -0,0 +1,17 @@
+package com.amd.aparapi.test;
+
+public class PostIncByteField{
+
+   byte z = (byte) 3;
+
+   byte incByte(byte _a) {
+      return _a++;
+   }
+
+   public void run() {
+
+      z = incByte(z++);
+
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PostIncInt.java b/test/codegen/src/java/com/amd/aparapi/test/PostIncInt.java
new file mode 100644
index 00000000..bff8fc0e
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PostIncInt.java
@@ -0,0 +1,39 @@
+package com.amd.aparapi.test;
+
+public class PostIncInt{
+
+   int foo(int a) {
+      return a;
+   }
+
+   public void run() {
+      int y = 2;
+      foo(y++);
+
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+int com_amd_aparapi_test_PostIncInt__foo(This *this, int a){
+   return(a);
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      int y = 2;
+      com_amd_aparapi_test_PostIncInt__foo(this,y++);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PostIncIntField.java b/test/codegen/src/java/com/amd/aparapi/test/PostIncIntField.java
new file mode 100644
index 00000000..80aaaf4d
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PostIncIntField.java
@@ -0,0 +1,17 @@
+package com.amd.aparapi.test;
+
+public class PostIncIntField{
+
+   int _y = 2;
+
+   int incInt(int a) {
+      return a++;
+   }
+
+   public void run() {
+
+      incInt(_y++);
+
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PostIncLocal.java b/test/codegen/src/java/com/amd/aparapi/test/PostIncLocal.java
new file mode 100644
index 00000000..9c3c884c
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PostIncLocal.java
@@ -0,0 +1,37 @@
+package com.amd.aparapi.test;
+
+public class PostIncLocal{
+
+   public void run() {
+      @SuppressWarnings("unused") boolean pass = false;
+      int i = 0;
+      if (i++ == 0)
+         pass = true;
+
+   }
+}
+/**{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;
+      if (i++==0){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PostIncLocalStandalone.java b/test/codegen/src/java/com/amd/aparapi/test/PostIncLocalStandalone.java
new file mode 100644
index 00000000..3a9ac0ca
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PostIncLocalStandalone.java
@@ -0,0 +1,33 @@
+package com.amd.aparapi.test;
+
+public class PostIncLocalStandalone{
+
+   public void run() {
+
+      int i = 0;
+      i++;
+
+   }
+}
+/**{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;
+   {
+      int i = 0;
+      i++;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PostIncLocalTwice.java b/test/codegen/src/java/com/amd/aparapi/test/PostIncLocalTwice.java
new file mode 100644
index 00000000..3b3beb6a
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PostIncLocalTwice.java
@@ -0,0 +1,37 @@
+package com.amd.aparapi.test;
+
+public class PostIncLocalTwice{
+
+   public void run() {
+      @SuppressWarnings("unused") boolean pass = false;
+      int i = 0;
+      if (i++ + i++ == 1)
+         pass = true;
+
+   }
+}
+/**{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;
+      if ((i++ + i++)==1){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PreDecArrayIndexAndElement.java b/test/codegen/src/java/com/amd/aparapi/test/PreDecArrayIndexAndElement.java
new file mode 100644
index 00000000..827d5b3b
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PreDecArrayIndexAndElement.java
@@ -0,0 +1,35 @@
+package com.amd.aparapi.test;
+
+public class PreDecArrayIndexAndElement{
+
+   int array[] = new int[4];
+
+   public void run() {
+      int i = 0;
+      --array[--i];
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *array;  
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global int *array,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->array = array;
+   this->passid = passid;
+   {
+      int i = 0;
+      this->array[--i]  = this->array[i] - 1;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PreDecArrayItem.java b/test/codegen/src/java/com/amd/aparapi/test/PreDecArrayItem.java
new file mode 100644
index 00000000..7bd88923
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PreDecArrayItem.java
@@ -0,0 +1,43 @@
+package com.amd.aparapi.test;
+
+public class PreDecArrayItem{
+
+   final static int START_SIZE = 128;
+
+   public int[] values = new int[START_SIZE];
+
+   public int[] results = new int[START_SIZE];
+
+   public void run() {
+      int y = 2;
+      values[y] = --results[y];
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *values;
+   __global int *results;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global int *values, 
+   __global int *results,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->values = values;
+   this->results = results;
+   this->passid = passid;
+   {
+      int y = 2;
+      this->values[y]  = --this->results[y];
+      return;
+   }
+}
+
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PreDecPostInc.java b/test/codegen/src/java/com/amd/aparapi/test/PreDecPostInc.java
new file mode 100644
index 00000000..94cf3dc1
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PreDecPostInc.java
@@ -0,0 +1,35 @@
+package com.amd.aparapi.test;
+
+public class PreDecPostInc{
+
+   public void run() {
+      int i = 0;
+      @SuppressWarnings("unused") int result = 0;
+      result = --i + i++;
+
+   }
+}
+/**{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;
+   {
+      int i = 0;
+      int result = 0;
+      i--;
+      result = i + i++;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PreIncArrayIndexAndElement.java b/test/codegen/src/java/com/amd/aparapi/test/PreIncArrayIndexAndElement.java
new file mode 100644
index 00000000..6438df47
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PreIncArrayIndexAndElement.java
@@ -0,0 +1,35 @@
+package com.amd.aparapi.test;
+
+public class PreIncArrayIndexAndElement{
+
+   int array[] = new int[4];
+
+   public void run() {
+      int i = 0;
+      ++array[++i];
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *array; 
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global int *array,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->array = array;
+   this->passid = passid;
+   {
+      int i = 0;
+      this->array[++i]  = this->array[i] + 1;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PreIncArrayItem.java b/test/codegen/src/java/com/amd/aparapi/test/PreIncArrayItem.java
new file mode 100644
index 00000000..0f1c7d8c
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PreIncArrayItem.java
@@ -0,0 +1,43 @@
+package com.amd.aparapi.test;
+
+public class PreIncArrayItem{
+
+   final static int START_SIZE = 128;
+
+   public int[] values = new int[START_SIZE];
+
+   public int[] results = new int[START_SIZE];
+
+   public void run() {
+      int y = 2;
+      values[y] = ++results[y];
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *values;
+   __global int *results;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global int *values, 
+   __global int *results,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->values = values;
+   this->results = results;
+   this->passid = passid;
+   {
+      int y = 2;
+      this->values[y]  = ++this->results[y];
+      return;
+   }
+}
+
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PreIncByte.java b/test/codegen/src/java/com/amd/aparapi/test/PreIncByte.java
new file mode 100644
index 00000000..051cc9f4
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PreIncByte.java
@@ -0,0 +1,61 @@
+package com.amd.aparapi.test;
+
+public class PreIncByte{
+
+   byte preIncByte(byte a) {
+      return ++a;
+   }
+
+   public void run() {
+      byte initValue = 0;
+      @SuppressWarnings("unused") byte result = preIncByte(++initValue);
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+char com_amd_aparapi_test_PreIncByte__preIncByte(This *this, char a){
+   a = (char )(a + 1);
+   return(a);
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      char initValue = 0;
+      char result = com_amd_aparapi_test_PreIncByte__preIncByte(this, ++initValue);
+      return;
+   }
+}
+}OpenCL}**/
+
+/**{OpenCL{
+typedef struct This_s{
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+char com_amd_aparapi_test_PreIncByte__preIncByte(This *this, char a){
+   return(a=(char )(a + 1));
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      char initValue = 0;
+      char result = com_amd_aparapi_test_PreIncByte__preIncByte(this, initValue=(char )(initValue + 1));
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PreIncByteField.java b/test/codegen/src/java/com/amd/aparapi/test/PreIncByteField.java
new file mode 100644
index 00000000..eefbf749
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PreIncByteField.java
@@ -0,0 +1,17 @@
+package com.amd.aparapi.test;
+
+public class PreIncByteField{
+
+   byte z = (byte) 3;
+
+   byte incByte(byte _a) {
+      return ++_a;
+   }
+
+   public void run() {
+
+      z = incByte(++z);
+
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PreIncInt.java b/test/codegen/src/java/com/amd/aparapi/test/PreIncInt.java
new file mode 100644
index 00000000..38e732f7
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PreIncInt.java
@@ -0,0 +1,41 @@
+package com.amd.aparapi.test;
+
+public class PreIncInt{
+
+   int preIncInt(int a) {
+      return a;
+   }
+
+   public void run() {
+
+      int y = 2;
+
+      preIncInt(++y);
+
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+int com_amd_aparapi_test_PreIncInt__preIncInt(This *this, int a){
+   return(a);
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      int y = 2;
+      com_amd_aparapi_test_PreIncInt__preIncInt(this,++y);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PreIncIntField.java b/test/codegen/src/java/com/amd/aparapi/test/PreIncIntField.java
new file mode 100644
index 00000000..70914b09
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PreIncIntField.java
@@ -0,0 +1,17 @@
+package com.amd.aparapi.test;
+
+public class PreIncIntField{
+
+   int y = 2;
+
+   int preIncInt(int _a) {
+      return ++_a;
+   }
+
+   public void run() {
+
+      preIncInt(++y);
+
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PreIncLocal.java b/test/codegen/src/java/com/amd/aparapi/test/PreIncLocal.java
new file mode 100644
index 00000000..80cc0377
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PreIncLocal.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class PreIncLocal{
+
+   public void run() {
+      @SuppressWarnings("unused") boolean pass = false;
+      int i = 0;
+      if (++i == 1)
+         pass = true;
+
+   }
+}
+/**{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;
+      i++;
+      if (i==1){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PreIncLocalStandalone.java b/test/codegen/src/java/com/amd/aparapi/test/PreIncLocalStandalone.java
new file mode 100644
index 00000000..fee16119
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PreIncLocalStandalone.java
@@ -0,0 +1,33 @@
+package com.amd.aparapi.test;
+
+public class PreIncLocalStandalone{
+
+   public void run() {
+
+      int i = 0;
+      ++i;
+
+   }
+}
+/**{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;
+   {
+      int i = 0;
+      i++;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/PreIncLocalTwice.java b/test/codegen/src/java/com/amd/aparapi/test/PreIncLocalTwice.java
new file mode 100644
index 00000000..eb815bdb
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/PreIncLocalTwice.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class PreIncLocalTwice{
+
+   public void run() {
+      @SuppressWarnings("unused") boolean pass = false;
+      int i = 0;
+      if (++i + ++i == 3)
+         pass = true;
+
+   }
+}
+/**{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;
+      i++;
+      if ((i++ + i)==3){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ReturnBooleanNewArray.java b/test/codegen/src/java/com/amd/aparapi/test/ReturnBooleanNewArray.java
new file mode 100644
index 00000000..3c33a06d
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ReturnBooleanNewArray.java
@@ -0,0 +1,14 @@
+package com.amd.aparapi.test;
+
+public class ReturnBooleanNewArray{
+
+   boolean[] returnBooleanNewArray() {
+
+      return new boolean[1024];
+   }
+
+   public void run() {
+      returnBooleanNewArray();
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ReturnBooleanVarArray.java b/test/codegen/src/java/com/amd/aparapi/test/ReturnBooleanVarArray.java
new file mode 100644
index 00000000..5a5572e5
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ReturnBooleanVarArray.java
@@ -0,0 +1,16 @@
+package com.amd.aparapi.test;
+
+public class ReturnBooleanVarArray{
+
+   boolean[] returnBooleanVarArray() {
+
+      boolean[] ba = new boolean[1024];
+
+      return ba;
+   }
+
+   public void run() {
+      returnBooleanVarArray();
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ReturnByteArrayNew.java b/test/codegen/src/java/com/amd/aparapi/test/ReturnByteArrayNew.java
new file mode 100644
index 00000000..ae4bf395
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ReturnByteArrayNew.java
@@ -0,0 +1,13 @@
+package com.amd.aparapi.test;
+
+public class ReturnByteArrayNew{
+
+   byte[] returnByteArrayNew() {
+      return new byte[1024];
+   }
+
+   public void run() {
+      returnByteArrayNew();
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ReturnByteArrayVar.java b/test/codegen/src/java/com/amd/aparapi/test/ReturnByteArrayVar.java
new file mode 100644
index 00000000..d8abe298
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ReturnByteArrayVar.java
@@ -0,0 +1,15 @@
+package com.amd.aparapi.test;
+
+public class ReturnByteArrayVar{
+
+   byte[] returnByteArrayVar() {
+      byte[] bytes = new byte[1024];
+      return bytes;
+   }
+
+   public void run() {
+
+      returnByteArrayVar();
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ReturnDoubleArrayNew.java b/test/codegen/src/java/com/amd/aparapi/test/ReturnDoubleArrayNew.java
new file mode 100644
index 00000000..a330d441
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ReturnDoubleArrayNew.java
@@ -0,0 +1,13 @@
+package com.amd.aparapi.test;
+
+public class ReturnDoubleArrayNew{
+
+   double[] returnDoubleArrayNew() {
+      return new double[1024];
+   }
+
+   public void run() {
+      returnDoubleArrayNew();
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ReturnDoubleArrayVar.java b/test/codegen/src/java/com/amd/aparapi/test/ReturnDoubleArrayVar.java
new file mode 100644
index 00000000..a3d0f1b3
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ReturnDoubleArrayVar.java
@@ -0,0 +1,15 @@
+package com.amd.aparapi.test;
+
+public class ReturnDoubleArrayVar{
+
+   double[] returnDoubleArrayVar() {
+      double[] doubles = new double[1024];
+      return doubles;
+   }
+
+   public void run() {
+
+      returnDoubleArrayVar();
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ReturnFloatArrayNew.java b/test/codegen/src/java/com/amd/aparapi/test/ReturnFloatArrayNew.java
new file mode 100644
index 00000000..caca36a2
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ReturnFloatArrayNew.java
@@ -0,0 +1,13 @@
+package com.amd.aparapi.test;
+
+public class ReturnFloatArrayNew{
+
+   float[] returnFloatArrayNew() {
+      return new float[1024];
+   }
+
+   public void run() {
+      returnFloatArrayNew();
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ReturnFloatArrayVar.java b/test/codegen/src/java/com/amd/aparapi/test/ReturnFloatArrayVar.java
new file mode 100644
index 00000000..5e973244
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ReturnFloatArrayVar.java
@@ -0,0 +1,15 @@
+package com.amd.aparapi.test;
+
+public class ReturnFloatArrayVar{
+
+   float[] returnFloatArrayVar() {
+      float[] floats = new float[1024];
+      return floats;
+   }
+
+   public void run() {
+
+      returnFloatArrayVar();
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ReturnIntArrayNew.java b/test/codegen/src/java/com/amd/aparapi/test/ReturnIntArrayNew.java
new file mode 100644
index 00000000..6ca7e75c
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ReturnIntArrayNew.java
@@ -0,0 +1,13 @@
+package com.amd.aparapi.test;
+
+public class ReturnIntArrayNew{
+
+   int[] returnIntArrayNew() {
+      return new int[1024];
+   }
+
+   public void run() {
+      returnIntArrayNew();
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ReturnIntArrayVar.java b/test/codegen/src/java/com/amd/aparapi/test/ReturnIntArrayVar.java
new file mode 100644
index 00000000..b9e5d7da
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ReturnIntArrayVar.java
@@ -0,0 +1,15 @@
+package com.amd.aparapi.test;
+
+public class ReturnIntArrayVar{
+
+   int[] returnIntArrayVar() {
+      int[] ints = new int[1024];
+      return ints;
+   }
+
+   public void run() {
+
+      returnIntArrayVar();
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ReturnLongArrayNew.java b/test/codegen/src/java/com/amd/aparapi/test/ReturnLongArrayNew.java
new file mode 100644
index 00000000..72e108d2
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ReturnLongArrayNew.java
@@ -0,0 +1,13 @@
+package com.amd.aparapi.test;
+
+public class ReturnLongArrayNew{
+
+   long[] returnLongArrayNew() {
+      return new long[1024];
+   }
+
+   public void run() {
+      returnLongArrayNew();
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ReturnLongArrayVar.java b/test/codegen/src/java/com/amd/aparapi/test/ReturnLongArrayVar.java
new file mode 100644
index 00000000..b5fa36c2
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ReturnLongArrayVar.java
@@ -0,0 +1,15 @@
+package com.amd.aparapi.test;
+
+public class ReturnLongArrayVar{
+
+   long[] returnLongArrayVar() {
+      long[] longs = new long[1024];
+      return longs;
+   }
+
+   public void run() {
+
+      returnLongArrayVar();
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ReturnPostIncInt.java b/test/codegen/src/java/com/amd/aparapi/test/ReturnPostIncInt.java
new file mode 100644
index 00000000..c06d6ac8
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ReturnPostIncInt.java
@@ -0,0 +1,35 @@
+package com.amd.aparapi.test;
+
+public class ReturnPostIncInt{
+
+   int returnPostIncInt(int value) {
+
+      return value++;
+   }
+
+   public void run() {
+      returnPostIncInt(3);
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+int com_amd_aparapi_test_ReturnPostIncInt__returnPostIncInt(This *this, int value){
+   return(value++);
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      com_amd_aparapi_test_ReturnPostIncInt__returnPostIncInt(this, 3);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ReturnPreIncInt.java b/test/codegen/src/java/com/amd/aparapi/test/ReturnPreIncInt.java
new file mode 100644
index 00000000..9f3da31b
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ReturnPreIncInt.java
@@ -0,0 +1,36 @@
+package com.amd.aparapi.test;
+
+public class ReturnPreIncInt{
+
+   int returnPreIncInt(int value) {
+
+      return ++value;
+   }
+
+   public void run() {
+      returnPreIncInt(3);
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+int com_amd_aparapi_test_ReturnPreIncInt__returnPreIncInt(This *this, int value){
+   value++;
+   return(value);
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      com_amd_aparapi_test_ReturnPreIncInt__returnPreIncInt(this, 3);
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ReturnShortArrayNew.java b/test/codegen/src/java/com/amd/aparapi/test/ReturnShortArrayNew.java
new file mode 100644
index 00000000..20f33bdd
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ReturnShortArrayNew.java
@@ -0,0 +1,13 @@
+package com.amd.aparapi.test;
+
+public class ReturnShortArrayNew{
+
+   short[] returnShortArrayNew() {
+      return new short[1024];
+   }
+
+   public void run() {
+      returnShortArrayNew();
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/ReturnShortArrayVar.java b/test/codegen/src/java/com/amd/aparapi/test/ReturnShortArrayVar.java
new file mode 100644
index 00000000..dfa51543
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/ReturnShortArrayVar.java
@@ -0,0 +1,15 @@
+package com.amd.aparapi.test;
+
+public class ReturnShortArrayVar{
+
+   short[] returnShortArrayVar() {
+      short[] shorts = new short[1024];
+      return shorts;
+   }
+
+   public void run() {
+
+      returnShortArrayVar();
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/RightShifts.java b/test/codegen/src/java/com/amd/aparapi/test/RightShifts.java
new file mode 100644
index 00000000..34e726d8
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/RightShifts.java
@@ -0,0 +1,46 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class RightShifts extends Kernel{
+
+   int iout[] = new int[10];
+
+   int i1, i2;
+
+   public void run() {
+      iout[1] = i1 >> i2;
+      iout[2] = i1 >>> i2;
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *iout;
+   int i1;
+   int i2;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global int *iout, 
+   int i1,
+   int i2,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->iout = iout;
+   this->i1 = i1;
+   this->i2 = i2;
+   this->passid = passid;
+   {
+      this->iout[1]  = this->i1 >> this->i2;
+      this->iout[2]  = ((unsigned int)this->i1) >> this->i2;
+      return;
+   }
+}
+
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/Sequence.java b/test/codegen/src/java/com/amd/aparapi/test/Sequence.java
new file mode 100644
index 00000000..1862e23d
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/Sequence.java
@@ -0,0 +1,27 @@
+package com.amd.aparapi.test;
+
+public class Sequence{
+   public void run() {
+      @SuppressWarnings("unused") boolean pass = false;
+
+   }
+}
+/**{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;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/StaticFieldStore.java b/test/codegen/src/java/com/amd/aparapi/test/StaticFieldStore.java
new file mode 100644
index 00000000..cdc733d7
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/StaticFieldStore.java
@@ -0,0 +1,12 @@
+package com.amd.aparapi.test;
+
+public class StaticFieldStore{
+   int[] ints = new int[1024];
+
+   static int foo = 6;
+
+   public void run() {
+      foo = ints[0];
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/SynchronizedMethods.java b/test/codegen/src/java/com/amd/aparapi/test/SynchronizedMethods.java
new file mode 100644
index 00000000..214574d3
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/SynchronizedMethods.java
@@ -0,0 +1,27 @@
+package com.amd.aparapi.test;
+
+public class SynchronizedMethods{
+   int[] ints = new int[1024];
+
+   synchronized int doIt(int a) {
+      return (int) (((int) 1) - a);
+   }
+
+   int doIt2(int a) {
+      return (int) (((int) 1) - a);
+   }
+
+   public void run() {
+      int foo = 1;
+      for (int i = 0; i < 1024; i++) {
+         if (i % 2 == 0) {
+            ints[i] = doIt(i);
+         } else {
+            synchronized (this) {
+               ints[i] = doIt2(foo);
+            }
+         }
+      }
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/Ternary.java b/test/codegen/src/java/com/amd/aparapi/test/Ternary.java
new file mode 100644
index 00000000..d486a94e
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/Ternary.java
@@ -0,0 +1,37 @@
+package com.amd.aparapi.test;
+
+public class Ternary{
+
+   float random() {
+      return (.1f);
+   }
+
+   public void run() {
+      @SuppressWarnings("unused") int count = (random() > .5f) ? +1 : -1;
+      @SuppressWarnings("unused") int foo = 3;
+   }
+
+}
+/**{OpenCL{
+typedef struct This_s{
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+float com_amd_aparapi_test_Ternary__random(This *this){
+   return(0.1f);
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      int count = (com_amd_aparapi_test_Ternary__random(this)>0.5f)?1:-1;
+      int foo = 3;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/TernaryAnd.java b/test/codegen/src/java/com/amd/aparapi/test/TernaryAnd.java
new file mode 100644
index 00000000..a214b7c0
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/TernaryAnd.java
@@ -0,0 +1,35 @@
+package com.amd.aparapi.test;
+
+public class TernaryAnd{
+   float random() {
+      return (.1f);
+   }
+
+   public void run() {
+
+      @SuppressWarnings("unused") int count = ((random()) > .8f) && ((random()) < .2f) ? +1 : -1;
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+
+float com_amd_aparapi_test_TernaryAnd__random(This *this){
+   return(0.1f);
+}
+__kernel void run(
+    int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      int count = (com_amd_aparapi_test_TernaryAnd__random(this)>0.8f && com_amd_aparapi_test_TernaryAnd__random(this)<0.2f)?1:-1;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/TernaryAndOr.java b/test/codegen/src/java/com/amd/aparapi/test/TernaryAndOr.java
new file mode 100644
index 00000000..4a1674ee
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/TernaryAndOr.java
@@ -0,0 +1,34 @@
+package com.amd.aparapi.test;
+
+public class TernaryAndOr{
+   float random() {
+      return (.1f);
+   }
+
+   public void run() {
+
+      @SuppressWarnings("unused") int count = random() == 0.f && (random() > .8f) || (random() < .2f) ? +1 : -1;
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+float com_amd_aparapi_test_TernaryAndOr__random(This *this){
+   return(0.1f);
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      int count = (com_amd_aparapi_test_TernaryAndOr__random(this)==0.0f && com_amd_aparapi_test_TernaryAndOr__random(this)>0.8f || com_amd_aparapi_test_TernaryAndOr__random(this)<0.2f)?1:-1;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/TernaryNested.java b/test/codegen/src/java/com/amd/aparapi/test/TernaryNested.java
new file mode 100644
index 00000000..7035c0be
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/TernaryNested.java
@@ -0,0 +1,31 @@
+package com.amd.aparapi.test;
+
+public class TernaryNested{
+   public void run() {
+      boolean a = false, b = false, c = false;
+      @SuppressWarnings("unused") int count = a ? b ? 1 : 2 : c ? 3 : 4;
+   }
+}
+/**{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 a = 0;
+      char b = 0;
+      char c = 0;
+      int count = (a!=0)?(b!=0)?1:2:(c!=0)?3:4;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/TernaryOr.java b/test/codegen/src/java/com/amd/aparapi/test/TernaryOr.java
new file mode 100644
index 00000000..db2ba4f1
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/TernaryOr.java
@@ -0,0 +1,36 @@
+package com.amd.aparapi.test;
+
+public class TernaryOr{
+   float random() {
+      return (.1f);
+   }
+
+   public void run() {
+
+      @SuppressWarnings("unused") int count = (random() > .8f || random() < .2f) ? +1 : -1;
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+float com_amd_aparapi_test_TernaryOr__random(This *this){
+   return(0.1f);
+}
+__kernel void run(
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->passid = passid;
+   {
+      int count = (com_amd_aparapi_test_TernaryOr__random(this)>0.8f || com_amd_aparapi_test_TernaryOr__random(this)<0.2f)?1:-1;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/TwoForLoops.java b/test/codegen/src/java/com/amd/aparapi/test/TwoForLoops.java
new file mode 100644
index 00000000..5297dc7d
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/TwoForLoops.java
@@ -0,0 +1,50 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class TwoForLoops extends Kernel{
+   public void run() {
+      for (int i = 0; i < size; i++) {
+         a[i] = i;
+      }
+
+      int sum = 0;
+      for (int i = 0; i < size; i++) {
+         sum += a[i];
+      }
+   }
+
+   final int size = 100;
+
+   int a[] = new int[size];
+
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *a;   
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+
+__kernel void run(
+   __global int *a,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->a = a;
+   this->passid = passid;
+   {
+      for (int i = 0; i<100; i++){
+         this->a[i]  = i;
+      }
+      int sum = 0;
+      for (int i = 0; i<100; i++){
+         sum = sum + this->a[i];
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/UnrelatedIfElsesWithCommonEndByte.java b/test/codegen/src/java/com/amd/aparapi/test/UnrelatedIfElsesWithCommonEndByte.java
new file mode 100644
index 00000000..0170efaf
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/UnrelatedIfElsesWithCommonEndByte.java
@@ -0,0 +1,84 @@
+package com.amd.aparapi.test;
+
+public class UnrelatedIfElsesWithCommonEndByte{
+   /*
+   1:   istore_1   (0:iconst_1)
+   3:   istore_2   (2:iconst_0)
+   5:   istore_3   (4:iconst_1)
+   7:   istore  4  (6:iconst_0)
+   10:  ifeq    39 (9:iload_1)        ?
+   14:  ifeq    23 (13:iload_2)       | ?
+   18:  istore  4  (17:iconst_1)      | |
+   20:  goto    26                    | | +
+   24:  istore  4  (23:  iconst_0)    | v |
+   27:  ifeq    36 (26:  iload_3)     |   v ?
+   31:  istore  4  (30:  iconst_1)    |     |
+   33:  goto    39                    |     | +
+   37:  istore  4  (36:  iconst_0)    |     v |
+   39:  return                        v       v
+   */
+   int width = 1024;
+
+   float scale = 1f;
+
+   int maxIterations = 10;
+
+   public void run() {
+      boolean a = true;
+      boolean b = false;
+      boolean c = true;
+      @SuppressWarnings("unused") boolean result = false;
+
+      if (a) {
+         if (b) {
+            result = true;
+         } else {
+            result = false;
+         }
+
+         if (c) {
+            result = true;
+         } else {
+            result = false;
+         }
+      }
+
+   }
+
+}
+/**{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 a = 1;
+      char b = 0;
+      char c = 1;
+      char result = 0;
+      if (a!=0){
+         if (b!=0){
+            result = 1;
+         } else {
+            result = 0;
+         }
+         if (c!=0){
+            result = 1;
+         } else {
+            result = 0;
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/UnrelatedIfsWithCommonEndByte.java b/test/codegen/src/java/com/amd/aparapi/test/UnrelatedIfsWithCommonEndByte.java
new file mode 100644
index 00000000..da23e2ab
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/UnrelatedIfsWithCommonEndByte.java
@@ -0,0 +1,67 @@
+package com.amd.aparapi.test;
+
+public class UnrelatedIfsWithCommonEndByte{
+   int width = 1024;
+
+   float scale = 1f;
+
+   int maxIterations = 10;
+
+   public void run() {
+      boolean a1 = true;
+      boolean a2 = true;
+      boolean b = false;
+      boolean c = true;
+      boolean outer = true;
+      @SuppressWarnings("unused") boolean result = false;
+      if (outer) {
+         if (a1 && !a2) {
+            // result = true;
+            if (b) {
+               result = true;
+            }
+            //result = false;
+            if (c) {
+               result = true;
+            }
+            //  result = false;
+         }
+      }
+
+   }
+
+}
+/**{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 a1 = 1;
+      char a2 = 1;
+      char b = 0;
+      char c = 1;
+      char outer = 1;
+      char result = 0;
+      if (outer!=0 && a1!=0 && a2==0){
+         if (b!=0){
+            result = 1;
+         }
+         if (c!=0){
+            result = 1;
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/UnrelatedNestedIfElses.java b/test/codegen/src/java/com/amd/aparapi/test/UnrelatedNestedIfElses.java
new file mode 100644
index 00000000..f71032e5
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/UnrelatedNestedIfElses.java
@@ -0,0 +1,70 @@
+package com.amd.aparapi.test;
+
+public class UnrelatedNestedIfElses{
+
+   int width = 1024;
+
+   float scale = 1f;
+
+   int maxIterations = 10;
+
+   public void run() {
+      boolean a = true;
+      boolean b = false;
+      boolean c = true;
+      @SuppressWarnings("unused") boolean result = false;
+
+      if (a) {
+         if (b) {
+            result = true;
+         } else {
+            result = false;
+         }
+      } else {
+         if (c) {
+            result = true;
+         } else {
+            result = false;
+         }
+      }
+
+   }
+
+}
+/**{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 a = 1;
+      char b = 0;
+      char c = 1;
+      char result = 0;
+      if (a!=0){
+         if (b!=0){
+            result = 1;
+         } else {
+            result = 0;
+         }
+      }else{
+         if (c!=0){
+            result = 1;
+         } else {
+            result = 0;
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/UseObject.java b/test/codegen/src/java/com/amd/aparapi/test/UseObject.java
new file mode 100644
index 00000000..8af70992
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/UseObject.java
@@ -0,0 +1,22 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class UseObject extends Kernel{
+   class Dummy{
+      public int n;
+   };
+
+   Dummy dummy = new Dummy();
+
+   public void run() {
+      out[0] = dummy.n;
+      out[1] = plainInt;
+   }
+
+   int out[] = new int[2];
+
+   int plainInt = -1;
+
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/UseObjectArrayLength.java b/test/codegen/src/java/com/amd/aparapi/test/UseObjectArrayLength.java
new file mode 100644
index 00000000..921951de
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/UseObjectArrayLength.java
@@ -0,0 +1,46 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class UseObjectArrayLength extends Kernel{
+   final class Dummy{
+      public int n;
+   };
+
+   int out[] = new int[2];
+
+   Dummy dummy[] = new Dummy[10];
+
+   public void run() {
+      out[0] = dummy.length;
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global int *out;
+   __global com_amd_aparapi_test_UseObjectArrayLength$Dummy *dummy;
+   int dummy__javaArrayLength;   
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   __global int *out,
+   __global com_amd_aparapi_test_UseObjectArrayLength$Dummy *dummy, 
+   int dummy__javaArrayLength,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->out = out;
+   this->dummy = dummy;
+   this->dummy__javaArrayLength = dummy__javaArrayLength;
+   this->passid = passid;
+   {
+      this->out[0]  = this->dummy__javaArrayLength;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/UsesArrayLength.java b/test/codegen/src/java/com/amd/aparapi/test/UsesArrayLength.java
new file mode 100644
index 00000000..1d8f0fcc
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/UsesArrayLength.java
@@ -0,0 +1,130 @@
+package com.amd.aparapi.test;
+
+import com.amd.aparapi.Kernel;
+
+public class UsesArrayLength extends Kernel{
+
+   boolean[] values;
+
+   boolean[] results;
+
+   boolean[] results2;
+
+   boolean actuallyDoIt(int index) {
+      int x = 0;
+
+      // in array index
+      @SuppressWarnings("unused") boolean y = values[values.length - index];
+
+      // in addition
+      x = index + results.length;
+
+      // in subtraction
+      return (results.length - x > 0);
+   }
+
+   public void run() {
+      int myId = 0;
+
+      // in comparison
+      boolean x = (values.length > 0);
+
+      // in bit AND and as argument
+      results[myId] = x & actuallyDoIt(values.length);
+
+      // Note results2.length is not used so there should not
+      // be a results2__javaArrayLength in the emitted source
+      results2[myId] = !results[myId];
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   __global char  *values;
+   int values__javaArrayLength;
+   __global char  *results;
+   int results__javaArrayLength;
+   __global char  *results2;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+char com_amd_aparapi_test_UsesArrayLength__actuallyDoIt(This *this, int index){
+   int x = 0;
+   char y = this->values[(this->values__javaArrayLength - index)];
+   x = index + this->results__javaArrayLength;
+   return(((this->results__javaArrayLength - x)>0)?1:0);
+}
+__kernel void run(
+   __global char  *values, 
+   int values__javaArrayLength, 
+   __global char  *results, 
+   int results__javaArrayLength, 
+   __global char  *results2,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->values = values;
+   this->values__javaArrayLength = values__javaArrayLength;
+   this->results = results;
+   this->results__javaArrayLength = results__javaArrayLength;
+   this->results2 = results2;
+   this->passid = passid;
+   {
+      int myId = 0;
+      char x = (this->values__javaArrayLength>0)?1:0;
+      this->results[myId]  = x & com_amd_aparapi_test_UsesArrayLength__actuallyDoIt(this, this->values__javaArrayLength);
+      this->results2[myId]  = (this->results[myId]==0)?1:0;
+      return;
+   }
+}
+}OpenCL}**/
+
+/**{OpenCL{
+typedef struct This_s{
+   __global char  *values;
+   int values__javaArrayLength;
+   __global char  *results;
+   int results__javaArrayLength;
+   __global char  *results2;
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+}
+char com_amd_aparapi_test_UsesArrayLength__actuallyDoIt(This *this, int index){
+   int x = 0;
+   char y = this->values[(this->values__javaArrayLength - index)];
+   x = index + this->results__javaArrayLength;
+   if ((this->results__javaArrayLength - x)>0){
+      return(1);
+   }
+   return(0);
+}
+__kernel void run(
+   __global char  *values, 
+   int values__javaArrayLength, 
+   __global char  *results, 
+   int results__javaArrayLength, 
+   __global char  *results2, 
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->values = values;
+   this->values__javaArrayLength = values__javaArrayLength;
+   this->results = results;
+   this->results__javaArrayLength = results__javaArrayLength;
+   this->results2 = results2;
+   this->passid = passid;
+   {
+      int myId = 0;
+      char x = (this->values__javaArrayLength>0)?1:0;
+      this->results[myId]  = x & com_amd_aparapi_test_UsesArrayLength__actuallyDoIt(this, this->values__javaArrayLength);
+      this->results2[myId]  = (this->results[myId]!=0)?0:1;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/UsesNew.java b/test/codegen/src/java/com/amd/aparapi/test/UsesNew.java
new file mode 100644
index 00000000..527bb2cf
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/UsesNew.java
@@ -0,0 +1,12 @@
+package com.amd.aparapi.test;
+
+public class UsesNew{
+   int[] ints = new int[1024];
+
+   public void run() {
+      @SuppressWarnings("unused") int foo = 1;
+
+      ints = new int[128];
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/UsesThrow.java b/test/codegen/src/java/com/amd/aparapi/test/UsesThrow.java
new file mode 100644
index 00000000..d9d490b3
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/UsesThrow.java
@@ -0,0 +1,26 @@
+package com.amd.aparapi.test;
+
+public class UsesThrow{
+   int[] ints = new int[1024];
+
+   int doIt(int a) throws Exception {
+      if (a < 0) {
+         throw new Exception("Zoinks!");
+      }
+      return (int) (((int) 1) - a);
+   }
+
+   public void run() {
+      @SuppressWarnings("unused") int foo = 1;
+      try {
+         for (int i = 0; i < 1024; i++) {
+            if (i % 2 == 0) {
+               ints[i] = doIt(i);
+            }
+         }
+      } catch (Exception e) {
+         // nothing
+      }
+   }
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/VarargsForEach.java b/test/codegen/src/java/com/amd/aparapi/test/VarargsForEach.java
new file mode 100644
index 00000000..edfc24c8
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/VarargsForEach.java
@@ -0,0 +1,24 @@
+package com.amd.aparapi.test;
+
+public class VarargsForEach{
+   public static int max(int... values) {
+      if (values.length == 0) {
+         return 0;
+      }
+
+      int max = Integer.MIN_VALUE;
+      for (int i : values) {
+         if (i > max)
+            max = i;
+      }
+      return max;
+   }
+
+   public void run() {
+      out[0] = max(1, 4, 5, 9, 3);
+   }
+
+   int out[] = new int[1];
+
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/VarargsSimple.java b/test/codegen/src/java/com/amd/aparapi/test/VarargsSimple.java
new file mode 100644
index 00000000..6ee4864c
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/VarargsSimple.java
@@ -0,0 +1,24 @@
+package com.amd.aparapi.test;
+
+public class VarargsSimple{
+   public static int max(int... values) {
+      if (values.length == 0) {
+         return 0;
+      }
+
+      int max = Integer.MIN_VALUE;
+      for (int i = 0; i < values.length; i++) {
+         if (values[i] > max)
+            max = i;
+      }
+      return max;
+   }
+
+   public void run() {
+      out[0] = max(1, 4, 5, 9, 3);
+   }
+
+   int out[] = new int[1];
+
+}
+/**{Throws{ClassParseException}Throws}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/While.java b/test/codegen/src/java/com/amd/aparapi/test/While.java
new file mode 100644
index 00000000..c76b523d
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/While.java
@@ -0,0 +1,38 @@
+package com.amd.aparapi.test;
+
+public class While{
+   public void run() {
+      @SuppressWarnings("unused") boolean pass = false;
+      int i = 0;
+      while (i < 10) {
+         pass = true;
+         i++;
+      }
+
+   }
+}
+/**{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;
+      for (; i<10; i++){
+         pass = 1;
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/WhileAndMandel.java b/test/codegen/src/java/com/amd/aparapi/test/WhileAndMandel.java
new file mode 100644
index 00000000..4671173d
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/WhileAndMandel.java
@@ -0,0 +1,90 @@
+package com.amd.aparapi.test;
+
+public class WhileAndMandel{
+   int width = 1024;
+
+   float scale = 1f;
+
+   int maxIterations = 10;
+
+   public void run() {
+      int tid = 0;
+
+      int i = tid % width;
+      int j = tid / width;
+
+      float x0 = ((i * scale) - ((scale / 2) * width)) / width;
+      float y0 = ((j * scale) - ((scale / 2) * width)) / width;
+
+      float x = x0;
+      float y = y0;
+
+      float x2 = x * x;
+      float y2 = y * y;
+
+      float scaleSquare = scale * scale;
+
+      int count = 0;
+      int iter = 0;
+      while ((x2 + y2 <= scaleSquare) && (iter < maxIterations)) {
+
+         y = 2 * x * y + y0;
+         x = x2 - y2 + x0;
+
+         x2 = x * x;
+         y2 = y * y;
+         count++;
+         ++iter;
+      }
+      @SuppressWarnings("unused") int value = (256 * count) / maxIterations;
+   }
+}
+/**{OpenCL{
+typedef struct This_s{
+   int width;
+   float scale;
+   int maxIterations;
+   
+   int passid;
+}This;
+int get_pass_id(This *this){
+   return this->passid;
+   }
+
+__kernel void run(
+   int width, 
+   float scale, 
+   int maxIterations,
+   int passid
+){
+   This thisStruct;
+   This* this=&thisStruct;
+   this->width = width;
+   this->scale = scale;
+   this->maxIterations = maxIterations;
+   this->passid = passid;
+   {
+      int tid = 0;
+      int i = tid % this->width;
+      int j = tid / this->width;
+      float x0 = (((float)i * this->scale) - ((this->scale / 2.0f) * (float)this->width)) / (float)this->width;
+      float y0 = (((float)j * this->scale) - ((this->scale / 2.0f) * (float)this->width)) / (float)this->width;
+      float x = x0;
+      float y = y0;
+      float x2 = x * x;
+      float y2 = y * y;
+      float scaleSquare = this->scale * this->scale;
+      int count = 0;
+      int iter = 0;
+      for (; (x2 + y2)<=scaleSquare && iter<this->maxIterations; iter++){
+         y = ((2.0f * x) * y) + y0;
+         x = (x2 - y2) + x0;
+         x2 = x * x;
+         y2 = y * y;
+         count++;
+      }
+      int value = (256 * count) / this->maxIterations;
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/WhileEmptyLoop.java b/test/codegen/src/java/com/amd/aparapi/test/WhileEmptyLoop.java
new file mode 100644
index 00000000..f4f65684
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/WhileEmptyLoop.java
@@ -0,0 +1,30 @@
+package com.amd.aparapi.test;
+
+public class WhileEmptyLoop{
+   public void run() {
+      int x = 10;
+      while (x-- != 0) {
+      }
+   }
+}
+/**{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;
+   {
+      for (int x = 10; x--!=0;){}
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/WhileIf.java b/test/codegen/src/java/com/amd/aparapi/test/WhileIf.java
new file mode 100644
index 00000000..fe73116a
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/WhileIf.java
@@ -0,0 +1,46 @@
+package com.amd.aparapi.test;
+
+public class WhileIf{
+   public void run() {
+
+      int a = 0;
+      int b = 0;
+      int c = 0;
+      int d = 0;
+
+      while (a == a) {
+         if (b == b) {
+            c = c;
+         }
+         //d = d; // remove this will work
+      }
+   }
+
+}
+/**{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;
+   {
+      int a = 0;
+      int b = 0;
+      int c = 0;
+      int d = 0;
+      for (; a==a; ){
+         if (b==b){
+            c = c;
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/WhileIfElse.java b/test/codegen/src/java/com/amd/aparapi/test/WhileIfElse.java
new file mode 100644
index 00000000..cf84769f
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/WhileIfElse.java
@@ -0,0 +1,49 @@
+package com.amd.aparapi.test;
+
+public class WhileIfElse{
+   public void run() {
+
+      int a = 0;
+      int b = 0;
+      int c = 0;
+      int d = 0;
+
+      while (a == a) {
+         if (b == b) {
+            c = c;
+         } else {
+            d = d;
+         }
+      }
+   }
+
+}
+/**{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;
+   {
+      int a = 0;
+      int b = 0;
+      int c = 0;
+      int d = 0;
+      for (; a==a; ){
+         if (b==b){
+            c = c;
+         } else {
+            d = d;
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/WhileWithoutMutator.java b/test/codegen/src/java/com/amd/aparapi/test/WhileWithoutMutator.java
new file mode 100644
index 00000000..90d250b5
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/WhileWithoutMutator.java
@@ -0,0 +1,30 @@
+package com.amd.aparapi.test;
+
+public class WhileWithoutMutator{
+   public void run() {
+      int x = 0;
+      while (x != 0) {
+      }
+   }
+}
+/**{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;
+   {
+      int x = 0;
+      for (; x!=0;){}
+      return;
+   }
+ }
+}OpenCL}**/
diff --git a/test/codegen/src/java/com/amd/aparapi/test/While_If_IfElseElse.java b/test/codegen/src/java/com/amd/aparapi/test/While_If_IfElseElse.java
new file mode 100644
index 00000000..d1789dea
--- /dev/null
+++ b/test/codegen/src/java/com/amd/aparapi/test/While_If_IfElseElse.java
@@ -0,0 +1,116 @@
+package com.amd.aparapi.test;
+
+public class While_If_IfElseElse{
+   public void run() {
+
+      int a = 0;
+      int b = 0;
+      int c = 0;
+      int d = 0;
+      int e = 0;
+      int f = 0;
+      int g = 0;
+      int h = 0;
+      int i = 0;
+      int j = 0;
+      int k = 0;
+      int l = 0;
+      int m = 0;
+      int n = 0;
+      int o = 0;
+      int p = 0;
+      int q = 0;
+      int r = 0;
+
+      while (a == a) {
+         b = b;
+         if (c == c) {
+            d = d;
+            if (e == e && f == f) {
+               g = g;
+            }
+         }
+         if (h == h && i == i) {
+            if (j == j) {
+               k = k;
+
+            }
+            if (l == l) {
+               if (m == m) {
+                  n = n;
+               } else if (o == o) {
+                  p = p;
+               } else {
+                  q = q;
+               }
+               r = r;
+            }
+         }
+      }
+
+   }
+
+}
+/**{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;
+   {
+      int a = 0;
+      int b = 0;
+      int c = 0;
+      int d = 0;
+      int e = 0;
+      int f = 0;
+      int g = 0;
+      int h = 0;
+      int i = 0;
+      int j = 0;
+      int k = 0;
+      int l = 0;
+      int m = 0;
+      int n = 0;
+      int o = 0;
+      int p = 0;
+      int q = 0;
+      int r = 0;
+      for (; a==a; ){
+         b = b;
+         if (c==c){
+            d = d;
+            if (e==e && f==f){
+               g = g;
+            }
+         }
+         
+         if (h==h && i==i){
+            if (j==j){
+               k = k;
+            }
+            if (l==l){
+               if (m==m){
+                  n = n;
+               } else {
+                  if (o==o){
+                     p = p;
+                  } else {
+                     q = q;
+                  }
+               }
+               r = r;
+            }
+         }
+      }
+      return;
+   }
+}
+}OpenCL}**/
-- 
GitLab