diff --git a/src/main/java/com/aparapi/internal/writer/BlockWriter.java b/src/main/java/com/aparapi/internal/writer/BlockWriter.java index 013239d0..45da63cd 100644 --- a/src/main/java/com/aparapi/internal/writer/BlockWriter.java +++ b/src/main/java/com/aparapi/internal/writer/BlockWriter.java @@ -80,8 +80,21 @@ public abstract class BlockWriter{ public final static String arrayDimMangleSuffix = "__javaArrayDimension"; + private static final Set openCLReservedIdentifiers = new HashSet(Arrays.asList( + "__constant", "__global", "__kernel", "__local", "__private", "auto", "bool", "break", "case", + "char", "complex", "constant", "continue", "default", "do", "double", "else", "enum", "extern", + "false", "float", "for", "global", "goto", "half", "if", "image1d_array_t", "image1d_buffer_t", + "image1d_t", "image2d_array_t", "image2d_depth_t", "image2d_t", "image3d_t", "inline", "int", + "kernel", "local", "long", "private", "read_only", "read_write", "register", "restrict", "return", + "sampler_t", "short", "signed", "sizeof", "static", "struct", "switch", "true", "typedef", "uchar", + "uint", "ulong", "union", "unsigned", "ushort", "void", "volatile", "while", "write_only")); + public abstract void write(String _string); + protected String mangleIdentifier(String identifier) { + return openCLReservedIdentifiers.contains(identifier) || identifier.startsWith("__") ? identifier + "_" : identifier; + } + public void writeln(String _string) { write(_string); newLine(); @@ -309,7 +322,7 @@ protected void writeGetterBlock(FieldEntry accessorVariableFieldEntry) { in(); newLine(); write("return this->"); - write(accessorVariableFieldEntry.getNameAndTypeEntry().getNameUTF8Entry().getUTF8()); + write(mangleIdentifier(accessorVariableFieldEntry.getNameAndTypeEntry().getNameUTF8Entry().getUTF8())); write(";"); out(); newLine(); @@ -417,7 +430,7 @@ public void writeInstruction(Instruction _instruction) throws CodeGenException { } else { final String descriptor = localVariableInfo.getVariableDescriptor(); write(convertType(descriptor, true, true)); - write(localVariableInfo.getVariableName()); + write(mangleIdentifier(localVariableInfo.getVariableName())); } } else { if (assignToLocalVariable.isDeclaration()) { @@ -431,7 +444,7 @@ public void writeInstruction(Instruction _instruction) throws CodeGenException { if (localVariableInfo == null) { throw new CodeGenException("outOfScope" + _instruction.getThisPC() + " = "); } else { - write(localVariableInfo.getVariableName() + " = "); + write(mangleIdentifier(localVariableInfo.getVariableName()) + " = "); } } @@ -481,7 +494,7 @@ public void writeInstruction(Instruction _instruction) throws CodeGenException { NameAndTypeEntry nameAndTypeEntry = ((AccessField) load).getConstantPoolFieldEntry().getNameAndTypeEntry(); if (isMultiDimensionalArray(nameAndTypeEntry)) { - String arrayName = nameAndTypeEntry.getNameUTF8Entry().getUTF8(); + String arrayName = mangleIdentifier(nameAndTypeEntry.getNameUTF8Entry().getUTF8()); write(" * this->" + arrayName + arrayDimMangleSuffix + dim); } } @@ -506,7 +519,7 @@ public void writeInstruction(Instruction _instruction) throws CodeGenException { writeThisRef(); } } - write(accessField.getConstantPoolFieldEntry().getNameAndTypeEntry().getNameUTF8Entry().getUTF8()); + write(mangleIdentifier(accessField.getConstantPoolFieldEntry().getNameAndTypeEntry().getNameUTF8Entry().getUTF8())); } else if (_instruction instanceof I_ARRAYLENGTH) { @@ -521,7 +534,7 @@ public void writeInstruction(Instruction _instruction) throws CodeGenException { dim++; } NameAndTypeEntry nameAndTypeEntry = ((AccessInstanceField) load).getConstantPoolFieldEntry().getNameAndTypeEntry(); - final String arrayName = nameAndTypeEntry.getNameUTF8Entry().getUTF8(); + final String arrayName = mangleIdentifier(nameAndTypeEntry.getNameUTF8Entry().getUTF8()); String dimSuffix = isMultiDimensionalArray(nameAndTypeEntry) ? Integer.toString(dim) : ""; write("this->" + arrayName + arrayLengthMangleSuffix + dimSuffix); } else if (_instruction instanceof AssignToField) { @@ -537,7 +550,7 @@ public void writeInstruction(Instruction _instruction) throws CodeGenException { writeThisRef(); } } - write(assignedField.getConstantPoolFieldEntry().getNameAndTypeEntry().getNameUTF8Entry().getUTF8()); + write(mangleIdentifier(assignedField.getConstantPoolFieldEntry().getNameAndTypeEntry().getNameUTF8Entry().getUTF8())); write("="); writeInstruction(assignedField.getValueToAssign()); } else if (_instruction instanceof Constant) { @@ -581,13 +594,13 @@ public void writeInstruction(Instruction _instruction) throws CodeGenException { } else if (_instruction instanceof AccessLocalVariable) { final AccessLocalVariable localVariableLoadInstruction = (AccessLocalVariable) _instruction; final LocalVariableInfo localVariable = localVariableLoadInstruction.getLocalVariableInfo(); - write(localVariable.getVariableName()); + write(mangleIdentifier(localVariable.getVariableName())); } else if (_instruction instanceof I_IINC) { final I_IINC location = (I_IINC) _instruction; final LocalVariableInfo localVariable = location.getLocalVariableInfo(); final int adjust = location.getAdjust(); - write(localVariable.getVariableName()); + write(mangleIdentifier(localVariable.getVariableName())); if (adjust == 1) { write("++"); } else if (adjust == -1) { @@ -688,7 +701,7 @@ public void writeInstruction(Instruction _instruction) throws CodeGenException { if (localVariableInfo == null) { throw new CodeGenException("outOfScope" + _instruction.getThisPC() + " = "); } else { - write(localVariableInfo.getVariableName() + " = "); + write(mangleIdentifier(localVariableInfo.getVariableName()) + " = "); } } @@ -703,7 +716,7 @@ public void writeInstruction(Instruction _instruction) throws CodeGenException { throw new CodeGenException("/* we can't declare this " + convertType(localVariableInfo.getVariableDescriptor(), true, false) + " here */"); } - write(localVariableInfo.getVariableName()); + write(mangleIdentifier(localVariableInfo.getVariableName())); write("="); writeInstruction(inlineAssignInstruction.getRhs()); } else if (_instruction.getByteCode().equals(ByteCode.FIELD_ARRAY_ELEMENT_ASSIGN)) { diff --git a/src/main/java/com/aparapi/internal/writer/KernelWriter.java b/src/main/java/com/aparapi/internal/writer/KernelWriter.java index 0a72a33f..66f4a929 100644 --- a/src/main/java/com/aparapi/internal/writer/KernelWriter.java +++ b/src/main/java/com/aparapi/internal/writer/KernelWriter.java @@ -241,7 +241,7 @@ public abstract class KernelWriter extends BlockWriter{ getterField = m.getAccessorVariableFieldEntry(); } if (getterField != null && isThis(_methodCall.getArg(0))) { - String fieldName = getterField.getNameAndTypeEntry().getNameUTF8Entry().getUTF8(); + String fieldName = mangleIdentifier(getterField.getNameAndTypeEntry().getNameUTF8Entry().getUTF8()); write("this->"); write(fieldName); return; @@ -285,7 +285,8 @@ public abstract class KernelWriter extends BlockWriter{ //assert refAccess instanceof I_GETFIELD : "ref should come from getfield"; final String fieldName = ((AccessField) refAccess).getConstantPoolFieldEntry().getNameAndTypeEntry() .getNameUTF8Entry().getUTF8(); - write(" &(this->" + fieldName); + final String mangledFieldName = mangleIdentifier(fieldName); + write(" &(this->" + mangledFieldName); write("["); writeInstruction(arrayAccess.getArrayIndex()); write("])"); @@ -423,13 +424,13 @@ public void writePragma(String _name, boolean _enable) { if (privateMemorySize == null) { assignLine.append("this->"); - assignLine.append(field.getName()); + assignLine.append(mangleIdentifier(field.getName())); assignLine.append(" = "); - assignLine.append(field.getName()); + assignLine.append(mangleIdentifier(field.getName())); } - argLine.append(field.getName()); - thisStructLine.append(field.getName()); + argLine.append(mangleIdentifier(field.getName())); + thisStructLine.append(mangleIdentifier(field.getName())); if (privateMemorySize == null) { assigns.add(assignLine.toString()); } @@ -449,7 +450,7 @@ public void writePragma(String _name, boolean _enable) { final StringBuilder lenAssignLine = new StringBuilder(); String suffix = numDimensions == 1 ? "" : Integer.toString(i); - String lenName = field.getName() + BlockWriter.arrayLengthMangleSuffix + suffix; + String lenName = mangleIdentifier(field.getName()) + BlockWriter.arrayLengthMangleSuffix + suffix; lenStructLine.append("int " + lenName); @@ -468,7 +469,7 @@ public void writePragma(String _name, boolean _enable) { final StringBuilder dimStructLine = new StringBuilder(); final StringBuilder dimArgLine = new StringBuilder(); final StringBuilder dimAssignLine = new StringBuilder(); - String dimName = field.getName() + BlockWriter.arrayDimMangleSuffix + suffix; + String dimName = mangleIdentifier(field.getName()) + BlockWriter.arrayDimMangleSuffix + suffix; dimStructLine.append("int " + dimName); @@ -562,7 +563,7 @@ public void writePragma(String _name, boolean _enable) { final String cType = convertType(field.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8(), true, false); assert cType != null : "could not find type for " + field.getNameAndTypeEntry().getDescriptorUTF8Entry().getUTF8(); - writeln(cType + " " + field.getNameAndTypeEntry().getNameUTF8Entry().getUTF8() + ";"); + writeln(cType + " " + mangleIdentifier(field.getNameAndTypeEntry().getNameUTF8Entry().getUTF8()) + ";"); } // compute total size for OpenCL buffer @@ -687,7 +688,7 @@ public void writePragma(String _name, boolean _enable) { } write(convertType(descriptor, true, false)); - write(lvi.getVariableName()); + write(mangleIdentifier(lvi.getVariableName())); alreadyHasFirstArg = true; localVariableIndex++; diff --git a/src/test/java/com/aparapi/codegen/test/OpenCLKeywordIdentifier.java b/src/test/java/com/aparapi/codegen/test/OpenCLKeywordIdentifier.java new file mode 100644 index 00000000..278d5ed7 --- /dev/null +++ b/src/test/java/com/aparapi/codegen/test/OpenCLKeywordIdentifier.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2016 - 2018 Syncleus, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.aparapi.codegen.test; + +public class OpenCLKeywordIdentifier { + + int[] global = new int[1]; + + int[] result = new int[1]; + + int compute(int kernel) { + int local = kernel + 1; + return local; + } + + public void run() { + int id = 0; + result[id] = compute(global[id]); + } +} diff --git a/src/test/java/com/aparapi/codegen/test/OpenCLKeywordIdentifierTest.java b/src/test/java/com/aparapi/codegen/test/OpenCLKeywordIdentifierTest.java new file mode 100644 index 00000000..9403b4ce --- /dev/null +++ b/src/test/java/com/aparapi/codegen/test/OpenCLKeywordIdentifierTest.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2016 - 2018 Syncleus, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.aparapi.codegen.test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.aparapi.Kernel; +import com.aparapi.internal.model.ClassModel; +import com.aparapi.internal.model.Entrypoint; +import com.aparapi.internal.writer.KernelWriter; + +public class OpenCLKeywordIdentifierTest { + + @Test + public void OpenCLKeywordIdentifierTest() throws Exception { + ClassModel classModel = ClassModel.createClassModel(OpenCLKeywordIdentifier.class); + Object kernelInstance = OpenCLKeywordIdentifier.class.getConstructor((Class[]) null).newInstance(); + Entrypoint entrypoint = classModel.getEntrypoint("run", kernelInstance instanceof Kernel ? kernelInstance : null); + String openCL = KernelWriter.writeToString(entrypoint); + + assertTrue(openCL, openCL.contains("__global int *global_")); + assertTrue(openCL, openCL.contains("this->global_ = global_")); + assertTrue(openCL, openCL.contains("int kernel_")); + assertTrue(openCL, openCL.contains("int local_ = kernel_ + 1")); + assertTrue(openCL, openCL.contains("return(local_)")); + + assertFalse(openCL, openCL.contains("__global int *global,")); + assertFalse(openCL, openCL.contains("this->global = global")); + assertFalse(openCL, openCL.contains("int kernel)")); + assertFalse(openCL, openCL.contains("int local = kernel + 1")); + } +}