/* * Copyright (c) 2017, Oracle and/or its affiliates. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials provided * with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors may be used to * endorse or promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.oracle.truffle.llvm.runtime.types.symbols; import java.util.regex.Pattern; public final class LLVMIdentifier { public static final String UNKNOWN = "<anon>"; private static final Pattern GLOBAL_VARNAME_PATTERN = Pattern.compile("@(\\\\01)?(\"[^\"]+\"|[\\w\\d\\u0024_\\u002e]+)"); private static final Pattern LOCAL_VARNAME_PATTERN = Pattern.compile("%(\"[^\"]+\"|[\\w\\d\\u0024_\\u002e]+)"); private LLVMIdentifier() { } public static String toGlobalIdentifier(String name) { if (GLOBAL_VARNAME_PATTERN.matcher(name).matches()) { // already a global identifier return name; } else { return "@" + escapeNameIfNecessary(name); } } public static String toLocalIdentifier(String name) { if (LOCAL_VARNAME_PATTERN.matcher(name).matches()) { // already a global identifier return name; } else { return "%" + escapeNameIfNecessary(name); } } private static final Pattern NUMERIC_VARNAME_PATTERN = Pattern.compile("\\d+"); public static String toBlockName(String name) { if (NUMERIC_VARNAME_PATTERN.matcher(name).matches()) { return String.format("%%\"%s\"", name); } else { return "%" + escapeNameIfNecessary(name); } } private static final String IMPLICIT_BLOCK_PREFIX = "implicit"; public static String toImplicitBlockName(int label) { return IMPLICIT_BLOCK_PREFIX + String.valueOf(label); } public static String extractLabelFromImplicitBlockName(String name) { return name.substring(IMPLICIT_BLOCK_PREFIX.length()); } public static boolean isImplicitBlockName(String name) { return name.startsWith(IMPLICIT_BLOCK_PREFIX); } public static String toTypeIdentifier(String name) { return escapeNameIfNecessary(name); } private static final Pattern UNESCAPED_VARNAME_PATTERN = Pattern.compile("[\\w\\d\\u0024_\\u002e]+"); private static final Pattern ESCAPED_VARNAME_PATTERN = Pattern.compile("(%|@|@\\\\01)?\"[^\"]+\""); private static String escapeNameIfNecessary(String unescaped) { // see http://releases.llvm.org/3.8.1/docs/LangRef.html#identifiers if (UNESCAPED_VARNAME_PATTERN.matcher(unescaped).matches()) { return unescaped; } else if (ESCAPED_VARNAME_PATTERN.matcher(unescaped).matches()) { // do not escape an already escaped name again return unescaped; } final StringBuilder builder = new StringBuilder("\""); for (int i = 0; i < unescaped.length(); i++) { final char c = unescaped.charAt(i); if (c == '\"' || c < ' ' || c > '~') { // use the format "\xx" where xx is the hex-value of c builder.append(String.format("\\%02x", c & 0xff)); } else { builder.append(c); } } builder.append('\"'); return builder.toString(); } }