50330
|
1 |
/*
|
|
2 |
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
4 |
*
|
|
5 |
* This code is free software; you can redistribute it and/or modify it
|
|
6 |
* under the terms of the GNU General Public License version 2 only, as
|
|
7 |
* published by the Free Software Foundation.
|
|
8 |
*
|
|
9 |
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
10 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
11 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
12 |
* version 2 for more details (a copy is included in the LICENSE file that
|
|
13 |
* accompanied this code).
|
|
14 |
*
|
|
15 |
* You should have received a copy of the GNU General Public License version
|
|
16 |
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
17 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
18 |
*
|
|
19 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
20 |
* or visit www.oracle.com if you need additional information or have any
|
|
21 |
* questions.
|
|
22 |
*/
|
|
23 |
package org.graalvm.compiler.replacements.processor;
|
|
24 |
|
|
25 |
import java.util.ArrayList;
|
|
26 |
import java.util.List;
|
|
27 |
|
|
28 |
import javax.annotation.processing.ProcessingEnvironment;
|
|
29 |
import javax.lang.model.element.TypeElement;
|
|
30 |
import javax.lang.model.type.TypeKind;
|
|
31 |
import javax.lang.model.type.TypeMirror;
|
|
32 |
import javax.tools.Diagnostic.Kind;
|
|
33 |
|
|
34 |
/**
|
|
35 |
* Pretty much copied from HotSpotSignature but using a different method for resolving types. This
|
|
36 |
* class should be rewritten, its just a quick hack to get signatures working.
|
|
37 |
*/
|
|
38 |
final class APHotSpotSignature {
|
|
39 |
|
|
40 |
private final List<String> arguments = new ArrayList<>();
|
|
41 |
private final String returnType;
|
|
42 |
private final String originalString;
|
|
43 |
private TypeMirror[] argumentTypes;
|
|
44 |
private TypeMirror returnTypeCache;
|
|
45 |
|
|
46 |
APHotSpotSignature(String signature) {
|
|
47 |
assert signature.length() > 0;
|
|
48 |
this.originalString = signature;
|
|
49 |
|
|
50 |
if (signature.charAt(0) == '(') {
|
|
51 |
int cur = 1;
|
|
52 |
while (cur < signature.length() && signature.charAt(cur) != ')') {
|
|
53 |
int nextCur = parseSignature(signature, cur);
|
|
54 |
arguments.add(signature.substring(cur, nextCur));
|
|
55 |
cur = nextCur;
|
|
56 |
}
|
|
57 |
|
|
58 |
cur++;
|
|
59 |
int nextCur = parseSignature(signature, cur);
|
|
60 |
returnType = signature.substring(cur, nextCur);
|
|
61 |
if (nextCur != signature.length()) {
|
|
62 |
throw new RuntimeException("Invalid trailing characters.");
|
|
63 |
}
|
|
64 |
} else {
|
|
65 |
returnType = null;
|
|
66 |
}
|
|
67 |
}
|
|
68 |
|
|
69 |
private static int parseSignature(String signature, int start) {
|
|
70 |
int cur = start;
|
|
71 |
char first;
|
|
72 |
do {
|
|
73 |
first = signature.charAt(cur++);
|
|
74 |
} while (first == '[');
|
|
75 |
|
|
76 |
switch (first) {
|
|
77 |
case 'L':
|
|
78 |
while (signature.charAt(cur) != ';') {
|
|
79 |
cur++;
|
|
80 |
}
|
|
81 |
cur++;
|
|
82 |
break;
|
|
83 |
case 'V':
|
|
84 |
case 'I':
|
|
85 |
case 'B':
|
|
86 |
case 'C':
|
|
87 |
case 'D':
|
|
88 |
case 'F':
|
|
89 |
case 'J':
|
|
90 |
case 'S':
|
|
91 |
case 'Z':
|
|
92 |
break;
|
|
93 |
default:
|
|
94 |
throw new RuntimeException("Invalid character at index " + cur + " in signature: " + signature);
|
|
95 |
}
|
|
96 |
return cur;
|
|
97 |
}
|
|
98 |
|
|
99 |
public int getParameterCount(boolean withReceiver) {
|
|
100 |
return arguments.size() + (withReceiver ? 1 : 0);
|
|
101 |
}
|
|
102 |
|
|
103 |
public TypeMirror getParameterType(ProcessingEnvironment env, int index) {
|
|
104 |
if (argumentTypes == null) {
|
|
105 |
argumentTypes = new TypeMirror[arguments.size()];
|
|
106 |
}
|
|
107 |
TypeMirror type = argumentTypes[index];
|
|
108 |
if (arguments.get(index) == null) {
|
|
109 |
throw new RuntimeException(String.format("Invalid argument at index %s.", index));
|
|
110 |
}
|
|
111 |
|
|
112 |
if (type == null) {
|
|
113 |
argumentTypes[index] = lookupType(env, arguments.get(index));
|
|
114 |
}
|
|
115 |
return argumentTypes[index];
|
|
116 |
}
|
|
117 |
|
|
118 |
private static TypeMirror lookupType(ProcessingEnvironment env, String binaryName) {
|
|
119 |
if (binaryName.length() == 1) {
|
|
120 |
TypeKind kind = fromPrimitiveOrVoidTypeChar(binaryName.charAt(0));
|
|
121 |
if (kind.isPrimitive()) {
|
|
122 |
return env.getTypeUtils().getPrimitiveType(kind);
|
|
123 |
} else if (kind == TypeKind.VOID) {
|
|
124 |
return env.getTypeUtils().getNoType(kind);
|
|
125 |
}
|
|
126 |
}
|
|
127 |
|
|
128 |
String canonicalName = binaryName;
|
|
129 |
if (canonicalName.startsWith("L") && canonicalName.endsWith(";")) {
|
|
130 |
canonicalName = canonicalName.substring(1, canonicalName.length() - 1);
|
|
131 |
}
|
|
132 |
env.getMessager().printMessage(Kind.ERROR, canonicalName);
|
|
133 |
|
|
134 |
int arrayDims = 0;
|
|
135 |
while (canonicalName.startsWith("[")) {
|
|
136 |
canonicalName = canonicalName.substring(1, canonicalName.length());
|
|
137 |
arrayDims++;
|
|
138 |
}
|
|
139 |
|
|
140 |
canonicalName = canonicalName.replaceAll("/", ".");
|
|
141 |
TypeElement typeElement = env.getElementUtils().getTypeElement(canonicalName);
|
|
142 |
if (typeElement == null) {
|
|
143 |
throw new RuntimeException(String.format("Type with name %s not found.", canonicalName));
|
|
144 |
}
|
|
145 |
TypeMirror mirror = typeElement.asType();
|
|
146 |
for (int i = 0; i < arrayDims; i++) {
|
|
147 |
mirror = env.getTypeUtils().getArrayType(mirror);
|
|
148 |
}
|
|
149 |
return mirror;
|
|
150 |
}
|
|
151 |
|
|
152 |
/**
|
|
153 |
* Returns the kind from the character describing a primitive or void.
|
|
154 |
*
|
|
155 |
* @param ch the character
|
|
156 |
* @return the kind
|
|
157 |
*/
|
|
158 |
public static TypeKind fromPrimitiveOrVoidTypeChar(char ch) {
|
|
159 |
switch (ch) {
|
|
160 |
case 'Z':
|
|
161 |
return TypeKind.BOOLEAN;
|
|
162 |
case 'C':
|
|
163 |
return TypeKind.CHAR;
|
|
164 |
case 'F':
|
|
165 |
return TypeKind.FLOAT;
|
|
166 |
case 'D':
|
|
167 |
return TypeKind.DOUBLE;
|
|
168 |
case 'B':
|
|
169 |
return TypeKind.BYTE;
|
|
170 |
case 'S':
|
|
171 |
return TypeKind.SHORT;
|
|
172 |
case 'I':
|
|
173 |
return TypeKind.INT;
|
|
174 |
case 'J':
|
|
175 |
return TypeKind.LONG;
|
|
176 |
case 'V':
|
|
177 |
return TypeKind.VOID;
|
|
178 |
}
|
|
179 |
throw new IllegalArgumentException("unknown primitive or void type character: " + ch);
|
|
180 |
}
|
|
181 |
|
|
182 |
public TypeMirror getReturnType(ProcessingEnvironment env) {
|
|
183 |
if (returnTypeCache == null) {
|
|
184 |
if (returnType == null) {
|
|
185 |
throw new RuntimeException("Invalid return type.");
|
|
186 |
}
|
|
187 |
returnTypeCache = lookupType(env, returnType);
|
|
188 |
}
|
|
189 |
return returnTypeCache;
|
|
190 |
}
|
|
191 |
|
|
192 |
@Override
|
|
193 |
public String toString() {
|
|
194 |
return "Signature<" + originalString + ">";
|
|
195 |
}
|
|
196 |
}
|