/* * Copyright (C) 2014 RoboVM AB * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/gpl-2.0.html>. */ package org.robovm.compiler; import static org.robovm.compiler.Types.*; import java.util.List; import org.robovm.compiler.trampoline.Trampoline; import soot.SootClass; import soot.SootField; import soot.SootFieldRef; import soot.SootMethod; import soot.SootMethodRef; /** * Generates symbols for functions and global values. All symbols generated by * the compiler must go through this class. */ public class Symbols { /** * Prefix used for functions representing actual method implementations. */ public static final String EXTERNAL_SYMBOL_PREFIX = "[J]"; /** * Prefix used for internal functions and values which doesn't correspond * to a method. */ public static final String INTERNAL_SYMBOL_PREFIX = "[j]"; /** * Prefix used for C functions. */ public static final String C_SYMBOL_PREFIX = "_j_"; public static String methodSymbol(SootMethod method) { return methodSymbol(method, null); } @SuppressWarnings("unchecked") public static String methodSymbol(SootMethodRef methodRef) { return methodSymbol(methodRef, null); } public static String methodSymbol(String owner, String name, List<soot.Type> parameterTypes, soot.Type returnType) { return methodSymbol(owner, name, parameterTypes, returnType, null); } public static String methodSymbol(String owner, String name, String desc) { return methodSymbol(owner, name, desc, null); } public static String methodAttributesSymbol(SootMethod method) { return methodSymbol(method, "mattributes"); } public static String callbackPtrSymbol(SootMethod method) { return methodSymbol(method, "callbackptr"); } public static String bridgePtrSymbol(SootMethod method) { return methodSymbol(method, "bridgeptr"); } public static boolean isCallbackCSymbol(String symbol) { return symbol.startsWith(C_SYMBOL_PREFIX) && symbol.endsWith("callback"); } public static String callbackCSymbol(SootMethod method) { return cMethodSymbol(method, "callback"); } public static boolean isCallbackInnerCSymbol(String symbol) { return symbol.startsWith(C_SYMBOL_PREFIX) && symbol.endsWith("callbackinner"); } public static String callbackInnerCSymbol(SootMethod method) { return cMethodSymbol(method, "callbackinner"); } public static boolean isBridgeCSymbol(String symbol) { return symbol.startsWith(C_SYMBOL_PREFIX) && symbol.endsWith("bridge"); } public static String bridgeCSymbol(SootMethod method) { return cMethodSymbol(method, "bridge"); } public static String globalValuePtrSymbol(SootMethod method) { return methodSymbol(method, "globalvalueptr"); } public static String nativeMethodPtrSymbol(String targetInternalName, String methodName, String methodDesc) { return methodSymbol(targetInternalName, methodName, methodDesc, "nativeptr"); } private static String methodSymbol(SootMethod method, String type) { return methodSymbol(method.makeRef(), type); } @SuppressWarnings("unchecked") private static String methodSymbol(SootMethodRef methodRef, String type) { return methodSymbol(getInternalName(methodRef.declaringClass()), methodRef.name(), methodRef.parameterTypes(), methodRef.returnType(), type); } private static String methodSymbol(String owner, String name, List<soot.Type> parameterTypes, soot.Type returnType, String type) { return methodSymbol(owner, name, getDescriptor(parameterTypes, returnType), type); } private static String methodSymbol(String owner, String name, String desc, String type) { StringBuilder sb = new StringBuilder(type == null ? EXTERNAL_SYMBOL_PREFIX : INTERNAL_SYMBOL_PREFIX); sb.append(owner.replace('/', '.')); sb.append('.'); sb.append(name); sb.append(desc); if (type != null) { sb.append('['); sb.append(type); sb.append(']'); } return sb.toString(); } private static String cMethodSymbol(SootMethod method, String type) { return cMethodSymbol(method.makeRef(), type); } @SuppressWarnings("unchecked") private static String cMethodSymbol(SootMethodRef methodRef, String type) { return cMethodSymbol(getInternalName(methodRef.declaringClass()), methodRef.name(), methodRef.parameterTypes(), methodRef.returnType(), type); } private static String cMethodSymbol(String owner, String name, List<soot.Type> parameterTypes, soot.Type returnType, String type) { return cMethodSymbol(owner, name, getDescriptor(parameterTypes, returnType), type); } private static String cMethodSymbol(String owner, String name, String desc, String type) { StringBuilder sb = new StringBuilder(C_SYMBOL_PREFIX); sb.append(Mangler.mangleNativeString(owner)); sb.append("_"); sb.append(Mangler.mangleNativeString(name)); sb.append("__"); sb.append(Mangler.mangleNativeString(desc.substring(1, desc.lastIndexOf(')')))); sb.append("__"); sb.append(Mangler.mangleNativeString(desc.substring(desc.lastIndexOf(')') + 1))); if (type != null) { sb.append("__"); sb.append(type); } return sb.toString(); } public static String linetableSymbol(String owner, String name, String desc) { return methodSymbol(owner, name, desc, "linetable"); } public static String linetableSymbol(SootMethod method) { return methodSymbol(method, "linetable"); } public static String methodSymbolPrefix(String owner) { StringBuilder sb = new StringBuilder(EXTERNAL_SYMBOL_PREFIX); sb.append(owner.replace('/', '.')); return sb.toString(); } public static String getterSymbol(SootField field) { return fieldSymbol(field, "get"); } public static String getterSymbol(SootFieldRef fieldRef) { return fieldSymbol(fieldRef, "get"); } public static String setterSymbol(SootField field) { return fieldSymbol(field, "set"); } public static String setterSymbol(SootFieldRef fieldRef) { return fieldSymbol(fieldRef, "set"); } public static String fieldAttributesSymbol(SootField field) { return fieldSymbol(field, "fattributes"); } private static String fieldSymbol(SootField field, String type) { return fieldSymbol(getInternalName(field.getDeclaringClass()), field.getName(), getDescriptor(field.getType()), type); } private static String fieldSymbol(SootFieldRef fieldRef, String type) { return fieldSymbol(getInternalName(fieldRef.declaringClass()), fieldRef.name(), getDescriptor(fieldRef.type()), type); } private static String fieldSymbol(String owner, String name, String desc, String type) { StringBuilder sb = new StringBuilder(INTERNAL_SYMBOL_PREFIX); sb.append(owner.replace('/', '.')); sb.append('.'); sb.append(name); sb.append('('); sb.append(desc); sb.append(')'); sb.append('['); sb.append(type); sb.append(']'); return sb.toString(); } public static String callbackSymbol(SootMethod method) { return functionWrapper(methodSymbol(method), "callback"); } public static String synchronizedWrapperSymbol(SootMethod method) { return functionWrapper(methodSymbol(method), "synchronized"); } public static String synchronizedWrapperSymbol(String owner, String name, String desc) { return functionWrapper(methodSymbol(owner, name, desc), "synchronized"); } public static String lookupWrapperSymbol(SootMethod method) { return functionWrapper(methodSymbol(method), "lookup"); } public static String lookupWrapperSymbol(String owner, String name, String desc) { return functionWrapper(methodSymbol(owner, name, desc), "lookup"); } public static String clinitWrapperSymbol(String targetFnName) { return functionWrapper(targetFnName, "clinit"); } private static String functionWrapper(String targetFnName, String type) { if (!targetFnName.startsWith(EXTERNAL_SYMBOL_PREFIX) && !targetFnName.startsWith(INTERNAL_SYMBOL_PREFIX)) { throw new IllegalArgumentException("Expected symbol prefix not found: " + targetFnName); } return INTERNAL_SYMBOL_PREFIX + targetFnName.substring(EXTERNAL_SYMBOL_PREFIX.length()) + "[" + type + "]"; } public static String allocatorSymbol(String classInternalName) { return classSymbol(classInternalName, "allocator"); } public static String instanceofSymbol(String classInternalName) { return classSymbol(classInternalName, "instanceof"); } public static String checkcastSymbol(String classInternalName) { return classSymbol(classInternalName, "checkcast"); } public static String trycatchenterSymbol(String classInternalName) { return classSymbol(classInternalName, "trycatchenter"); } public static String ldcInternalSymbol(String classInternalName) { return classSymbol(classInternalName, "ldc"); } public static String ldcExternalSymbol(String classInternalName) { return classSymbol(classInternalName, "ldcext"); } public static String infoSymbol(String classInternalName) { return classSymbol(classInternalName, "info"); } public static String infoStructSymbol(String classInternalName) { return classSymbol(classInternalName, "infostruct"); } public static String typeInfoSymbol(String classInternalName) { return classSymbol(classInternalName, "typeinfo"); } public static String vtableSymbol(String classInternalName) { return classSymbol(classInternalName, "vtable"); } public static String itableSymbol(String classInternalName) { return classSymbol(classInternalName, "itable"); } public static String itableSymbol(String classInternalName, int n) { return classSymbol(classInternalName, "itable" + n); } public static String itablesSymbol(String classInternalName) { return classSymbol(classInternalName, "itables"); } public static String classAttributesSymbol(SootClass sootClass) { return classSymbol(getInternalName(sootClass), "cattributes"); } private static String classSymbol(String classInternalName, String type) { return INTERNAL_SYMBOL_PREFIX + classInternalName.replace('/', '.') + "[" + type + "]"; } public static String arrayinstanceofSymbol(String descriptor) { return arraySymbol(descriptor, "arrayinstanceof"); } public static String arraycheckcastSymbol(String descriptor) { return arraySymbol(descriptor, "arraycheckcast"); } public static String anewarraySymbol(String descriptor) { return arraySymbol(descriptor, "anewarray"); } public static String multianewarraySymbol(String descriptor) { return arraySymbol(descriptor, "multianewarray"); } public static String arrayldcSymbol(String descriptor) { return arraySymbol(descriptor, "arrayldc"); } public static String arrayPtrSymbol(String descriptor) { return arraySymbol(descriptor, "arrayptr"); } private static String arraySymbol(String descriptor, String type) { return INTERNAL_SYMBOL_PREFIX + descriptor + "[" + type + "]"; } public static String nativeCallMethodSymbol(String owner, String name, String desc) { return methodSymbol(owner, name, desc, "NativeCall"); } public static String trampolineMethodSymbol(Trampoline t, String caller, String owner, String name, String desc) { return methodSymbol(owner, name, desc, t.getClass().getSimpleName() + "(" + caller + ")"); } public static String trampolineMethodSymbol(Trampoline t, String caller, String owner, String name, String desc, String runtimeClass) { return methodSymbol(owner, name, desc, t.getClass().getSimpleName() + "(" + caller + "," + runtimeClass + ")"); } public static String trampolineFieldSymbol(Trampoline t, String caller, String owner, String name, String desc) { return fieldSymbol(owner, name, desc, t.getClass().getSimpleName() + "(" + caller + ")"); } public static String trampolineFieldSymbol(Trampoline t, String caller, String owner, String name, String desc, String runtimeClass) { return fieldSymbol(owner, name, desc, t.getClass().getSimpleName() + "(" + caller + "," + runtimeClass + ")"); } public static String trampolineSymbol(Trampoline t, String caller, String targetClass) { return classSymbol(targetClass, t.getClass().getSimpleName() + "(" + caller + ")"); } public static String ldcStringPtrSymbol(byte[] modUtf8) { // NOTE: The symbols generated here are also used from C code in classinfo.c. Do not change. return Strings.getStringVarName(modUtf8) + "_ptr"; } public static String ldcStringSymbol(byte[] modUtf8) { return INTERNAL_SYMBOL_PREFIX + Strings.getStringVarName(modUtf8) + "[ldcstring]"; } }