1 /* 2 * Copyright (c) 2015, 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.verifier; 24 25 import java.io.PrintWriter; 26 import java.util.List; 27 import java.util.Set; 28 import java.util.TreeSet; 29 30 import javax.annotation.processing.ProcessingEnvironment; 31 import javax.lang.model.element.ExecutableElement; 32 import javax.lang.model.element.Modifier; 33 import javax.lang.model.element.TypeElement; 34 import javax.lang.model.element.VariableElement; 35 import javax.lang.model.type.DeclaredType; 36 import javax.lang.model.type.TypeMirror; 37 38 import org.graalvm.compiler.api.replacements.Fold; 39 import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; 40 import org.graalvm.compiler.replacements.verifier.InjectedDependencies.WellKnownDependency; 41 42 /** 43 * Create graph builder plugins for {@link Fold} methods. 44 */ 45 public class GeneratedFoldPlugin extends GeneratedPlugin { 46 47 public GeneratedFoldPlugin(ExecutableElement intrinsicMethod) { 48 super(intrinsicMethod); 49 } 50 51 private static TypeMirror stringType(ProcessingEnvironment env) { 52 return env.getElementUtils().getTypeElement("java.lang.String").asType(); 53 } 54 55 @Override 56 public void extraImports(Set<String> imports) { 57 imports.add("jdk.vm.ci.meta.JavaConstant"); 58 imports.add("jdk.vm.ci.meta.JavaKind"); 59 imports.add("org.graalvm.compiler.nodes.ConstantNode"); 60 } 61 62 @Override 63 protected InjectedDependencies createExecute(ProcessingEnvironment env, PrintWriter out) { 64 InjectedDependencies deps = new InjectedDependencies(); 65 List<? extends VariableElement> params = intrinsicMethod.getParameters(); 66 67 int argCount = 0; 68 Object receiver; 69 if (intrinsicMethod.getModifiers().contains(Modifier.STATIC)) { 70 receiver = intrinsicMethod.getEnclosingElement(); 71 } else { 72 receiver = "arg0"; 73 TypeElement type = (TypeElement) intrinsicMethod.getEnclosingElement(); 74 constantArgument(env, out, deps, argCount, type.asType(), argCount); 75 argCount++; 76 } 77 78 int firstArg = argCount; 79 for (VariableElement param : params) { 80 if (param.getAnnotation(InjectedParameter.class) == null) { 81 constantArgument(env, out, deps, argCount, param.asType(), argCount); 82 } else { 83 out.printf(" assert checkInjectedArgument(b, args[%d], targetMethod);\n", argCount); 84 out.printf(" %s arg%d = %s;\n", param.asType(), argCount, deps.use(env, (DeclaredType) param.asType())); 85 } 86 argCount++; 87 } 88 89 Set<String> suppressWarnings = new TreeSet<>(); 90 if (intrinsicMethod.getAnnotation(Deprecated.class) != null) { 91 suppressWarnings.add("deprecation"); 92 } 93 if (hasRawtypeWarning(intrinsicMethod.getReturnType())) { 94 suppressWarnings.add("rawtypes"); 95 } 96 for (VariableElement param : params) { 97 if (hasUncheckedWarning(param.asType())) { 98 suppressWarnings.add("unchecked"); 99 } 100 } 101 if (suppressWarnings.size() > 0) { 102 out.printf(" @SuppressWarnings({"); 103 String sep = ""; 104 for (String suppressWarning : suppressWarnings) { 105 out.printf("%s\"%s\"", sep, suppressWarning); 106 sep = ", "; 107 } 108 out.printf("})\n"); 109 } 110 111 out.printf(" %s result = %s.%s(", getErasedType(intrinsicMethod.getReturnType()), receiver, intrinsicMethod.getSimpleName()); 112 if (argCount > firstArg) { 113 out.printf("arg%d", firstArg); 114 for (int i = firstArg + 1; i < argCount; i++) { 115 out.printf(", arg%d", i); 116 } 117 } 118 out.printf(");\n"); 119 120 TypeMirror returnType = intrinsicMethod.getReturnType(); 121 switch (returnType.getKind()) { 122 case BOOLEAN: 123 out.printf(" JavaConstant constant = JavaConstant.forInt(result ? 1 : 0);\n"); 124 break; 125 case BYTE: 126 case SHORT: 127 case CHAR: 128 case INT: 129 out.printf(" JavaConstant constant = JavaConstant.forInt(result);\n"); 130 break; 131 case LONG: 132 out.printf(" JavaConstant constant = JavaConstant.forLong(result);\n"); 133 break; 134 case FLOAT: 135 out.printf(" JavaConstant constant = JavaConstant.forFloat(result);\n"); 136 break; 137 case DOUBLE: 138 out.printf(" JavaConstant constant = JavaConstant.forDouble(result);\n"); 139 break; 140 case ARRAY: 141 case TYPEVAR: 142 case DECLARED: 143 if (returnType.equals(stringType(env))) { 144 out.printf(" JavaConstant constant = %s.forString(result);\n", deps.use(WellKnownDependency.CONSTANT_REFLECTION)); 145 } else { 146 out.printf(" JavaConstant constant = %s.forObject(result);\n", deps.use(WellKnownDependency.SNIPPET_REFLECTION)); 147 } 148 break; 149 default: 150 throw new IllegalArgumentException(returnType.toString()); 151 } 152 153 out.printf(" ConstantNode node = ConstantNode.forConstant(constant, %s, %s);\n", deps.use(WellKnownDependency.META_ACCESS), deps.use(WellKnownDependency.STRUCTURED_GRAPH)); 154 out.printf(" b.push(JavaKind.%s, node);\n", getReturnKind(intrinsicMethod)); 155 out.printf(" return true;\n"); 156 157 return deps; 158 } 159 }