From a3fdbe65eebf3947ac02794330bbc0107f0c054c Mon Sep 17 00:00:00 2001 From: xiongdi Date: Wed, 13 May 2026 16:20:41 +0800 Subject: [PATCH] Escape OpenCL keyword identifiers --- .../aparapi/internal/writer/BlockWriter.java | 35 +++++++++----- .../aparapi/internal/writer/KernelWriter.java | 30 ++++++------ .../codegen/test/OpenCLKeywordIdentifier.java | 26 ++++++++++ .../test/OpenCLKeywordIdentifierTest.java | 48 +++++++++++++++++++ 4 files changed, 114 insertions(+), 25 deletions(-) create mode 100644 src/test/java/com/aparapi/codegen/test/OpenCLKeywordIdentifier.java create mode 100644 src/test/java/com/aparapi/codegen/test/OpenCLKeywordIdentifierTest.java diff --git a/src/main/java/com/aparapi/internal/writer/BlockWriter.java b/src/main/java/com/aparapi/internal/writer/BlockWriter.java index 013239d0..d5f3e80e 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 = Collections.unmodifiableSet(new HashSet(Arrays.asList( + "auto", "break", "case", "char", "const", "constant", "__constant", "continue", "default", "do", "double", + "else", "enum", "extern", "float", "for", "global", "__global", "goto", "if", "inline", "int", "kernel", + "__kernel", "local", "__local", "long", "private", "__private", "read_only", "__read_only", "register", + "restrict", "return", "short", "signed", "sizeof", "static", "struct", "switch", "typedef", "union", + "unsigned", "void", "volatile", "while", "write_only", "__write_only", "bool", "half", "quad", "complex", + "imaginary", "sampler_t", "event_t", "image1d_t", "image1d_array_t", "image1d_buffer_t", "image2d_t", + "image2d_array_t", "image3d_t"))); + public abstract void write(String _string); + protected String mangleIdentifier(String identifier) { + return openCLReservedIdentifiers.contains(identifier) ? "aparapi_" + 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()) + " = "); } } @@ -482,7 +495,7 @@ public void writeInstruction(Instruction _instruction) throws CodeGenException { NameAndTypeEntry nameAndTypeEntry = ((AccessField) load).getConstantPoolFieldEntry().getNameAndTypeEntry(); if (isMultiDimensionalArray(nameAndTypeEntry)) { String arrayName = nameAndTypeEntry.getNameUTF8Entry().getUTF8(); - write(" * this->" + arrayName + arrayDimMangleSuffix + dim); + write(" * this->" + mangleIdentifier(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) { @@ -523,7 +536,7 @@ public void writeInstruction(Instruction _instruction) throws CodeGenException { NameAndTypeEntry nameAndTypeEntry = ((AccessInstanceField) load).getConstantPoolFieldEntry().getNameAndTypeEntry(); final String arrayName = nameAndTypeEntry.getNameUTF8Entry().getUTF8(); String dimSuffix = isMultiDimensionalArray(nameAndTypeEntry) ? Integer.toString(dim) : ""; - write("this->" + arrayName + arrayLengthMangleSuffix + dimSuffix); + write("this->" + mangleIdentifier(arrayName) + arrayLengthMangleSuffix + dimSuffix); } else if (_instruction instanceof AssignToField) { final AssignToField assignedField = (AssignToField) _instruction; @@ -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..8e4fa177 100644 --- a/src/main/java/com/aparapi/internal/writer/KernelWriter.java +++ b/src/main/java/com/aparapi/internal/writer/KernelWriter.java @@ -243,7 +243,7 @@ public abstract class KernelWriter extends BlockWriter{ if (getterField != null && isThis(_methodCall.getArg(0))) { String fieldName = getterField.getNameAndTypeEntry().getNameUTF8Entry().getUTF8(); write("this->"); - write(fieldName); + write(mangleIdentifier(fieldName)); return; } boolean noCL = _methodEntry.getOwnerClassModel().getNoCLMethods() @@ -285,7 +285,7 @@ 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); + write(" &(this->" + mangleIdentifier(fieldName)); write("["); writeInstruction(arrayAccess.getArrayIndex()); write("])"); @@ -344,6 +344,8 @@ public void writePragma(String _name, boolean _enable) { final StringBuilder argLine = new StringBuilder(); final StringBuilder assignLine = new StringBuilder(); + final String rawFieldName = field.getName(); + final String fieldName = mangleIdentifier(rawFieldName); String signature = field.getDescriptor(); boolean isPointer = false; @@ -352,11 +354,11 @@ public void writePragma(String _name, boolean _enable) { // check the suffix - String type = field.getName().endsWith(Kernel.LOCAL_SUFFIX) ? __local - : (field.getName().endsWith(Kernel.CONSTANT_SUFFIX) ? __constant : __global); + String type = rawFieldName.endsWith(Kernel.LOCAL_SUFFIX) ? __local + : (rawFieldName.endsWith(Kernel.CONSTANT_SUFFIX) ? __constant : __global); Integer privateMemorySize = null; try { - privateMemorySize = _entryPoint.getClassModel().getPrivateMemorySize(field.getName()); + privateMemorySize = _entryPoint.getClassModel().getPrivateMemorySize(rawFieldName); } catch (ClassParseException e) { throw new CodeGenException(e); } @@ -423,13 +425,13 @@ public void writePragma(String _name, boolean _enable) { if (privateMemorySize == null) { assignLine.append("this->"); - assignLine.append(field.getName()); + assignLine.append(fieldName); assignLine.append(" = "); - assignLine.append(field.getName()); + assignLine.append(fieldName); } - argLine.append(field.getName()); - thisStructLine.append(field.getName()); + argLine.append(fieldName); + thisStructLine.append(fieldName); if (privateMemorySize == null) { assigns.add(assignLine.toString()); } @@ -441,7 +443,7 @@ public void writePragma(String _name, boolean _enable) { // Add int field into "this" struct for supporting java arraylength op // named like foo__javaArrayLength - if (isPointer && _entryPoint.getArrayFieldArrayLengthUsed().contains(field.getName()) || isPointer && numDimensions > 1) { + if (isPointer && _entryPoint.getArrayFieldArrayLengthUsed().contains(rawFieldName) || isPointer && numDimensions > 1) { for (int i = 0; i < numDimensions; i++) { final StringBuilder lenStructLine = new StringBuilder(); @@ -449,7 +451,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 = fieldName + BlockWriter.arrayLengthMangleSuffix + suffix; lenStructLine.append("int " + lenName); @@ -468,7 +470,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 = fieldName + BlockWriter.arrayDimMangleSuffix + suffix; dimStructLine.append("int " + dimName); @@ -562,7 +564,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 +689,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..48fbb79c --- /dev/null +++ b/src/test/java/com/aparapi/codegen/test/OpenCLKeywordIdentifier.java @@ -0,0 +1,26 @@ +/** + * 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[] constant = new int[1024]; + + public void run() { + int kernel = 0; + int global = kernel + 1; + constant[kernel] = global; + } +} 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..1347c6b0 --- /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 com.aparapi.internal.model.ClassModel; +import com.aparapi.internal.model.Entrypoint; +import com.aparapi.internal.writer.KernelWriter; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class OpenCLKeywordIdentifierTest { + @Test + public void OpenCLKeywordIdentifierTest() throws Exception { + ClassModel classModel = ClassModel.createClassModel(OpenCLKeywordIdentifier.class); + Entrypoint entrypoint = classModel.getEntrypoint("run", null); + String actual = KernelWriter.writeToString(entrypoint); + + assertTrue(actual.contains("__global int *aparapi_constant")); + assertTrue(actual.contains("this->aparapi_constant = aparapi_constant")); + assertTrue(actual.contains("int aparapi_kernel = 0")); + assertTrue(actual.contains("int aparapi_global = aparapi_kernel + 1")); + assertTrue(actual.contains("this->aparapi_constant[aparapi_kernel] = aparapi_global")); + + assertFalse(actual.contains("__global int *constant")); + assertFalse(actual.contains("int kernel = 0")); + assertFalse(actual.contains("int global =")); + } + + @Test + public void OpenCLKeywordIdentifierTestWorksWithCaching() throws Exception { + OpenCLKeywordIdentifierTest(); + } +}