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<3)</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<3 || i>10)</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<n> | + * | / iload<n> Increment(varref<n>++) + * 0, 0 istore<n> - iadd | + * | \ i_const_1 | + * B B + * + * A A + * | | + * +1, 0 <t>load<n> | + * | / iload<n> Increment( varref<n>++) + * 0, 0 <t>store<n> - i2<t> 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>µ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