diff --git a/src/main/java/com/aparapi/internal/writer/BlockWriter.java b/src/main/java/com/aparapi/internal/writer/BlockWriter.java index 013239d0..25e89d30 100644 --- a/src/main/java/com/aparapi/internal/writer/BlockWriter.java +++ b/src/main/java/com/aparapi/internal/writer/BlockWriter.java @@ -295,6 +295,7 @@ public void writeSequence(Instruction _first, Instruction _last) throws CodeGenE if (instruction instanceof CompositeInstruction) { writeComposite((CompositeInstruction) instruction); } else if (!instruction.getByteCode().equals(ByteCode.NONE)) { + writeInlineLocalDeclarations(instruction); newLine(); writeInstruction(instruction); write(";"); @@ -304,6 +305,37 @@ public void writeSequence(Instruction _first, Instruction _last) throws CodeGenE } + private void writeInlineLocalDeclarations(Instruction instruction) throws CodeGenException { + final Map declarations = new LinkedHashMap(); + collectInlineLocalDeclarations(instruction, declarations); + for (final LocalVariableInfo localVariableInfo : declarations.values()) { + newLine(); + write(convertType(localVariableInfo.getVariableDescriptor(), true, false)); + write(localVariableInfo.getVariableName()); + write(";"); + } + } + + private void collectInlineLocalDeclarations(Instruction instruction, Map declarations) { + if (instruction == null) { + return; + } + + if (instruction instanceof InlineAssignInstruction) { + final InlineAssignInstruction inlineAssignInstruction = (InlineAssignInstruction) instruction; + final AssignToLocalVariable assignToLocalVariable = inlineAssignInstruction.getAssignToLocalVariable(); + final LocalVariableInfo localVariableInfo = assignToLocalVariable.getLocalVariableInfo(); + if ((localVariableInfo != null) && assignToLocalVariable.isDeclaration()) { + declarations.put(localVariableInfo.getVariableIndex(), localVariableInfo); + } + collectInlineLocalDeclarations(inlineAssignInstruction.getRhs(), declarations); + } + + for (Instruction child = instruction.getFirstChild(); child != null; child = child.getNextExpr()) { + collectInlineLocalDeclarations(child, declarations); + } + } + protected void writeGetterBlock(FieldEntry accessorVariableFieldEntry) { write("{"); in(); @@ -698,10 +730,8 @@ public void writeInstruction(Instruction _instruction) throws CodeGenException { final AssignToLocalVariable assignToLocalVariable = inlineAssignInstruction.getAssignToLocalVariable(); final 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, false) - + " here */"); + if (localVariableInfo == null) { + throw new CodeGenException("outOfScope" + _instruction.getThisPC() + " = "); } write(localVariableInfo.getVariableName()); write("="); diff --git a/src/test/java/com/aparapi/codegen/test/AssignAndPassAsParameterSimpleTest.java b/src/test/java/com/aparapi/codegen/test/AssignAndPassAsParameterSimpleTest.java index efff6cd5..2f49b265 100644 --- a/src/test/java/com/aparapi/codegen/test/AssignAndPassAsParameterSimpleTest.java +++ b/src/test/java/com/aparapi/codegen/test/AssignAndPassAsParameterSimpleTest.java @@ -15,15 +15,36 @@ */ package com.aparapi.codegen.test; -import com.aparapi.internal.exception.ClassParseException; -import com.aparapi.internal.exception.CodeGenException; -import org.junit.Ignore; import org.junit.Test; public class AssignAndPassAsParameterSimpleTest extends com.aparapi.codegen.CodeGenJUnitBase { - private static final String[] expectedOpenCL = null; - private static final Class expectedException = CodeGenException.class; + private static final String[] expectedOpenCL = { + "typedef struct This_s{\n" + + "\n" + + " int passid;\n" + + " }This;\n" + + " int get_pass_id(This *this){\n" + + " return this->passid;\n" + + " }\n" + + "\n" + + " void com_aparapi_codegen_test_AssignAndPassAsParameterSimple__actuallyDoIt(This *this, int a){\n" + + " return;\n" + + " }\n" + + " __kernel void run(\n" + + " int passid\n" + + " ){\n" + + " This thisStruct;\n" + + " This* this=&thisStruct;\n" + + " this->passid = passid;\n" + + " {\n" + + " int z;\n" + + " com_aparapi_codegen_test_AssignAndPassAsParameterSimple__actuallyDoIt(this, z=1);\n" + + " return;\n" + + " }\n" + + " }\n" + + " "}; + private static final Class expectedException = null; @Test public void AssignAndPassAsParameterSimpleTest() {