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.util.HashMap;
  26 import java.util.Iterator;
  27 
  28 import javax.annotation.processing.ProcessingEnvironment;
  29 import javax.lang.model.element.ExecutableElement;
  30 import javax.lang.model.type.DeclaredType;
  31 import javax.lang.model.type.TypeMirror;
  32 
  33 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
  34 import org.graalvm.compiler.replacements.verifier.InjectedDependencies.Dependency;
  35 
  36 public class InjectedDependencies implements Iterable<Dependency> {
  37 
  38     public abstract static class Dependency {
  39 
  40         public final String name;
  41         public final String type;
  42 
  43         private Dependency(String name, String type) {
  44             this.name = name;
  45             this.type = type;
  46         }
  47 
  48         public abstract String inject(ExecutableElement inject);
  49     }
  50 
  51     private static final class InjectedDependency extends Dependency {
  52 
  53         private InjectedDependency(String name, String type) {
  54             super(name, type);
  55         }
  56 
  57         @Override
  58         public String inject(ExecutableElement inject) {
  59             return String.format("injection.getInjectedArgument(%s.class)", type);
  60         }
  61     }
  62 
  63     private static final class StampDependency extends Dependency {
  64 
  65         private StampDependency() {
  66             super("returnStamp", "org.graalvm.compiler.core.common.type.Stamp");
  67         }
  68 
  69         @Override
  70         public String inject(ExecutableElement inject) {
  71             NodeIntrinsic nodeIntrinsic = inject.getAnnotation(NodeIntrinsic.class);
  72             return String.format("injection.getReturnStamp(%s.class, %s)", GeneratedPlugin.getErasedType(inject.getReturnType()), nodeIntrinsic != null && nodeIntrinsic.returnStampIsNonNull());
  73         }
  74     }
  75 
  76     public enum WellKnownDependency {
  77         CONSTANT_REFLECTION("b.getConstantReflection()", "jdk.vm.ci.meta.ConstantReflectionProvider"),
  78         META_ACCESS("b.getMetaAccess()", "jdk.vm.ci.meta.MetaAccessProvider"),
  79         RETURN_STAMP(new StampDependency()),
  80         SNIPPET_REFLECTION(new InjectedDependency("snippetReflection", "org.graalvm.compiler.api.replacements.SnippetReflectionProvider")),
  81         STAMP_PROVIDER("b.getStampProvider()", "org.graalvm.compiler.nodes.spi.StampProvider"),
  82         STRUCTURED_GRAPH("b.getGraph()", "org.graalvm.compiler.nodes.StructuredGraph");
  83 
  84         private final String expr;
  85         private final String type;
  86         private final Dependency generateMember;
  87 
  88         WellKnownDependency(String expr, String type) {
  89             this.expr = expr;
  90             this.type = type;
  91             this.generateMember = null;
  92         }
  93 
  94         WellKnownDependency(Dependency generateMember) {
  95             this.expr = generateMember.name;
  96             this.type = generateMember.type;
  97             this.generateMember = generateMember;
  98         }
  99 
 100         private TypeMirror getType(ProcessingEnvironment env) {
 101             return env.getElementUtils().getTypeElement(type).asType();
 102         }
 103     }
 104 
 105     private final HashMap<String, Dependency> deps;
 106 
 107     public InjectedDependencies() {
 108         deps = new HashMap<>();
 109     }
 110 
 111     public String use(WellKnownDependency wellKnown) {
 112         if (wellKnown.generateMember != null) {
 113             deps.put(wellKnown.type, wellKnown.generateMember);
 114         }
 115         return wellKnown.expr;
 116     }
 117 
 118     public String use(ProcessingEnvironment env, DeclaredType type) {
 119         for (WellKnownDependency wellKnown : WellKnownDependency.values()) {
 120             if (env.getTypeUtils().isAssignable(wellKnown.getType(env), type)) {
 121                 return use(wellKnown);
 122             }
 123         }
 124 
 125         String typeName = type.toString();
 126         Dependency ret = deps.get(typeName);
 127         if (ret == null) {
 128             ret = new InjectedDependency("injected" + type.asElement().getSimpleName(), typeName);
 129             deps.put(typeName, ret);
 130         }
 131         return ret.name;
 132     }
 133 
 134     @Override
 135     public Iterator<Dependency> iterator() {
 136         return deps.values().iterator();
 137     }
 138 
 139     public boolean isEmpty() {
 140         return deps.isEmpty();
 141     }
 142 }