Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 165 additions & 13 deletions src/main/java/com/aparapi/internal/writer/BlockWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ public abstract class BlockWriter{

public final static String arrayDimMangleSuffix = "__javaArrayDimension";

private final Stack<Set<String>> hoistedLocalDeclarations = new Stack<Set<String>>();

public abstract void write(String _string);

public void writeln(String _string) {
Expand Down Expand Up @@ -320,13 +322,161 @@ protected void writeGetterBlock(FieldEntry accessorVariableFieldEntry) {
public void writeBlock(Instruction _first, Instruction _last) throws CodeGenException {
write("{");
in();
writeHoistedLocalDeclarations(_first, _last);
writeSequence(_first, _last);
out();
newLine();

write("}");
}

private void writeHoistedLocalDeclarations(Instruction _first, Instruction _last) {
final LinkedHashMap<String, LocalVariableInfo> declarations = new LinkedHashMap<String, LocalVariableInfo>();
final int blockEndPc = _last == null ? Integer.MAX_VALUE : _last.getThisPC();

for (Instruction instruction = _first; instruction != _last; instruction = instruction.getNextExpr()) {
collectHoistedLocalDeclarations(instruction, blockEndPc, declarations);
}

for (final LocalVariableInfo localVariableInfo : declarations.values()) {
final String key = localVariableDeclarationKey(localVariableInfo);
if (!getHoistedLocalDeclarations().contains(key)) {
getHoistedLocalDeclarations().add(key);
newLine();
writeLocalDeclaration(localVariableInfo, true);
write(";");
}
}
}

private void collectHoistedLocalDeclarations(Instruction instruction, int blockEndPc,
Map<String, LocalVariableInfo> declarations) {
if (instruction instanceof CompositeInstruction) {
if (skipCompositeHoistingScan(instruction)) {
return;
}
final int compositeEndPc = instruction.getThisPC();
collectEscapingHoistedLocalDeclarations(instruction.getFirstChild(), null, compositeEndPc, blockEndPc, declarations);
} else {
collectHoistedLocalDeclarationsInExpression(instruction, blockEndPc, declarations, false);
}
}

private void collectEscapingHoistedLocalDeclarations(Instruction first, Instruction last, int nestedBlockEndPc, int blockEndPc,
Map<String, LocalVariableInfo> declarations) {
for (Instruction instruction = first; instruction != last; instruction = instruction.getNextExpr()) {
if (instruction instanceof CompositeInstruction) {
if (!skipCompositeHoistingScan(instruction)) {
collectEscapingHoistedLocalDeclarations(instruction.getFirstChild(), null, nestedBlockEndPc, blockEndPc, declarations);
}
} else {
collectHoistedLocalDeclarationsInExpression(instruction, blockEndPc, declarations, nestedBlockEndPc, true);
}
}
}

private boolean skipCompositeHoistingScan(Instruction instruction) {
return instruction instanceof CompositeForSunInstruction || instruction instanceof CompositeForEclipseInstruction
|| instruction instanceof CompositeEmptyLoopInstruction || instruction instanceof CompositeArbitraryScopeInstruction;
}

private void collectHoistedLocalDeclarationsInExpression(Instruction instruction, int blockEndPc,
Map<String, LocalVariableInfo> declarations, boolean includeRootAssignment) {
collectHoistedLocalDeclarationsInExpression(instruction, blockEndPc, declarations, -1, includeRootAssignment);
}

private void collectHoistedLocalDeclarationsInExpression(Instruction instruction, int blockEndPc,
Map<String, LocalVariableInfo> declarations, int mustEscapePc, boolean includeRootAssignment) {
if (instruction == null) {
return;
}

if (includeRootAssignment && instruction instanceof AssignToLocalVariable) {
collectHoistedLocalDeclaration((AssignToLocalVariable) instruction, blockEndPc, declarations, mustEscapePc);
}

if (instruction.getByteCode().equals(ByteCode.INLINE_ASSIGN)) {
final InlineAssignInstruction inlineAssignInstruction = (InlineAssignInstruction) instruction;
collectHoistedLocalDeclaration(inlineAssignInstruction.getAssignToLocalVariable(), blockEndPc, declarations, mustEscapePc);
} else if (instruction.getByteCode().equals(ByteCode.MULTI_ASSIGN)) {
final MultiAssignInstruction multiAssignInstruction = (MultiAssignInstruction) instruction;
AssignToLocalVariable from = (AssignToLocalVariable) multiAssignInstruction.getFrom();
final AssignToLocalVariable last = (AssignToLocalVariable) multiAssignInstruction.getTo();
while (from != last) {
collectHoistedLocalDeclaration(from, blockEndPc, declarations, mustEscapePc);
from = (AssignToLocalVariable) ((Instruction) from).getNextExpr();
}
collectHoistedLocalDeclarationsInExpression(multiAssignInstruction.getCommon(), blockEndPc, declarations, mustEscapePc, true);
}

for (Instruction child = instruction.getFirstChild(); child != null; child = child.getNextExpr()) {
collectHoistedLocalDeclarationsInExpression(child, blockEndPc, declarations, mustEscapePc, true);
}
}

private void collectHoistedLocalDeclaration(AssignToLocalVariable assignToLocalVariable, int blockEndPc,
Map<String, LocalVariableInfo> declarations, int mustEscapePc) {
if (!assignToLocalVariable.isDeclaration()) {
return;
}

final LocalVariableInfo localVariableInfo = assignToLocalVariable.getLocalVariableInfo();
if (localVariableInfo == null) {
return;
}

if ((mustEscapePc >= 0) && (localVariableInfo.getEnd() <= mustEscapePc)) {
return;
}

if (localVariableInfo.getEnd() <= blockEndPc) {
declarations.put(localVariableDeclarationKey(localVariableInfo), localVariableInfo);
}
}

private void writeLocalDeclaration(LocalVariableInfo localVariableInfo, boolean initialize) {
writeLocalType(localVariableInfo);
write(localVariableInfo.getVariableName());
if (initialize) {
write(" = ");
write(defaultValueForLocalVariable(localVariableInfo));
}
}

private void writeLocalType(LocalVariableInfo localVariableInfo) {
final String descriptor = localVariableInfo.getVariableDescriptor();
if (descriptor.startsWith("[")) {
write(" __global ");
}
write(convertType(descriptor, true, false));
}

private String defaultValueForLocalVariable(LocalVariableInfo localVariableInfo) {
final String descriptor = localVariableInfo.getVariableDescriptor();
if ("F".equals(descriptor) || "float".equals(descriptor)) {
return "0.0f";
} else if ("D".equals(descriptor) || "double".equals(descriptor)) {
return "0.0";
} else if ("J".equals(descriptor) || "long".equals(descriptor)) {
return "0L";
} else {
return "0";
}
}

private Set<String> getHoistedLocalDeclarations() {
return hoistedLocalDeclarations.isEmpty() ? Collections.<String> emptySet() : hoistedLocalDeclarations.peek();
}

private boolean isHoistedLocalDeclaration(LocalVariableInfo localVariableInfo) {
return getHoistedLocalDeclarations().contains(localVariableDeclarationKey(localVariableInfo));
}

private String localVariableDeclarationKey(LocalVariableInfo localVariableInfo) {
return localVariableInfo.getVariableIndex() + ":" + localVariableInfo.getVariableDescriptor() + ":"
+ localVariableInfo.getVariableName();
}

public Instruction writeConditional(BranchSet _branchSet) throws CodeGenException {
return (writeConditional(_branchSet, false));
}
Expand Down Expand Up @@ -420,16 +570,11 @@ public void writeInstruction(Instruction _instruction) throws CodeGenException {
write(localVariableInfo.getVariableName());
}
} else {
if (assignToLocalVariable.isDeclaration()) {
final String descriptor = localVariableInfo.getVariableDescriptor();
// Arrays always map to __global arrays
if (descriptor.startsWith("[")) {
write(" __global ");
}
write(convertType(descriptor, true, false));
}
if (localVariableInfo == null) {
throw new CodeGenException("outOfScope" + _instruction.getThisPC() + " = ");
} else if (assignToLocalVariable.isDeclaration() && !isHoistedLocalDeclaration(localVariableInfo)) {
writeLocalType(localVariableInfo);
write(localVariableInfo.getVariableName() + " = ");
} else {
write(localVariableInfo.getVariableName() + " = ");
}
Expand Down Expand Up @@ -682,11 +827,11 @@ public void writeInstruction(Instruction _instruction) throws CodeGenException {
for (AssignToLocalVariable alv = stack.pop(); alv != null; alv = stack.size() > 0 ? stack.pop() : null) {

final LocalVariableInfo localVariableInfo = alv.getLocalVariableInfo();
if (alv.isDeclaration()) {
write(convertType(localVariableInfo.getVariableDescriptor(), true, false));
}
if (localVariableInfo == null) {
throw new CodeGenException("outOfScope" + _instruction.getThisPC() + " = ");
} else if (alv.isDeclaration() && !isHoistedLocalDeclaration(localVariableInfo)) {
writeLocalType(localVariableInfo);
write(localVariableInfo.getVariableName() + " = ");
} else {
write(localVariableInfo.getVariableName() + " = ");
}
Expand All @@ -698,7 +843,9 @@ public void writeInstruction(Instruction _instruction) throws CodeGenException {
final AssignToLocalVariable assignToLocalVariable = inlineAssignInstruction.getAssignToLocalVariable();

final LocalVariableInfo localVariableInfo = assignToLocalVariable.getLocalVariableInfo();
if (assignToLocalVariable.isDeclaration()) {
if (localVariableInfo == null) {
throw new CodeGenException("outOfScope" + _instruction.getThisPC() + " = ");
} else if (assignToLocalVariable.isDeclaration() && !isHoistedLocalDeclaration(localVariableInfo)) {
// 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 */");
Expand Down Expand Up @@ -870,7 +1017,12 @@ public void writeMethodBody(MethodModel _methodModel) throws CodeGenException {
FieldEntry accessorVariableFieldEntry = _methodModel.getAccessorVariableFieldEntry();
writeGetterBlock(accessorVariableFieldEntry);
} else {
writeBlock(_methodModel.getExprHead(), null);
hoistedLocalDeclarations.push(new HashSet<String>());
try {
writeBlock(_methodModel.getExprHead(), null);
} finally {
hoistedLocalDeclarations.pop();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,26 @@ public void run() {
actuallyDoIt(z = 1);
}
}
/**{Throws{CodeGenException}Throws}**/
/**{OpenCL{
typedef struct This_s{
int passid;
}This;
int get_pass_id(This *this){
return this->passid;
}
void com_aparapi_codegen_test_AssignAndPassAsParameterSimple__actuallyDoIt(This *this, int a){
return;
}
__kernel void run(
int passid
){
This thisStruct;
This* this=&thisStruct;
this->passid = passid;
{
int z = 0;
com_aparapi_codegen_test_AssignAndPassAsParameterSimple__actuallyDoIt(this, z=1);
return;
}
}
}OpenCL}**/
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,34 @@
*/
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<? extends com.aparapi.internal.exception.AparapiException> expectedException = CodeGenException.class;
private static final String[] expectedOpenCL = {
"typedef struct This_s{\n"
+ " int passid;\n"
+ " }This;\n"
+ " int get_pass_id(This *this){\n"
+ " return this->passid;\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 = 0;\n"
+ " com_aparapi_codegen_test_AssignAndPassAsParameterSimple__actuallyDoIt(this, z=1);\n"
+ " return;\n"
+ " }\n"
+ " }\n"
+ " "};
private static final Class<? extends com.aparapi.internal.exception.AparapiException> expectedException = null;

@Test
public void AssignAndPassAsParameterSimpleTest() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ int get_pass_id(This *this){
return this->passid;
}

void func(This *this, int _arg){
void com_aparapi_codegen_test_FirstAssignInExpression__func(This *this, int _arg){
return;
}
__kernel void run(
Expand All @@ -49,8 +49,9 @@ __kernel void run(
This* this=&thisStruct;
this->passid = passid;
{
int result;
func(this, result = 0);
int result = 0;
int value = 1;
com_aparapi_codegen_test_FirstAssignInExpression__func(this, result=value);
return;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,17 @@ __kernel void run(
This* this=&thisStruct;
this->passid = passid;
{
int assignMe = 0;
int value = 1;
int result=0;
int assignMe=0;
if (true){
int result = 0;
if (value==value){
result = assignMe = value;
}else{
assignMe =1;
result=2;
} else {
assignMe = 1;
result = 2;
}
result++;
assignMe++;
return;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package com.aparapi.codegen.test;

import org.junit.Ignore;
import org.junit.Test;

public class FirstAssignInExpression2Test extends com.aparapi.codegen.CodeGenJUnitBase {
Expand All @@ -35,29 +34,28 @@ public class FirstAssignInExpression2Test extends com.aparapi.codegen.CodeGenJUn
+ " This* this=&thisStruct;\n"
+ " this->passid = passid;\n"
+ " {\n"
+ " int assignMe = 0;\n"
+ " int value = 1;\n"
+ " int result=0;\n"
+ " int assignMe=0;\n"
+ " if (true){\n"
+ " int result = 0;\n"
+ " if (value==value){\n"
+ " result = assignMe = value;\n"
+ " }else{\n"
+ " assignMe =1;\n"
+ " result=2;\n"
+ " } else {\n"
+ " assignMe = 1;\n"
+ " result = 2;\n"
+ " }\n"
+ " result++;\n"
+ " assignMe++;\n"
+ " return;\n"
+ " }\n"
+ " }\n"
+ " "};
private static final Class<? extends com.aparapi.internal.exception.AparapiException> expectedException = null;

@Ignore
@Test
public void FirstAssignInExpression2Test() {
test(com.aparapi.codegen.test.FirstAssignInExpression2.class, expectedException, expectedOpenCL);
}

@Ignore
@Test
public void FirstAssignInExpression2TestWorksWithCaching() {
test(com.aparapi.codegen.test.FirstAssignInExpression2.class, expectedException, expectedOpenCL);
Expand Down
Loading