001/* 002 * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.lir.jtt; 024 025import static com.oracle.graal.lir.LIRValueUtil.*; 026 027import java.lang.annotation.*; 028import java.lang.reflect.*; 029import java.util.stream.*; 030 031import jdk.internal.jvmci.meta.*; 032 033import com.oracle.graal.api.replacements.*; 034import com.oracle.graal.compiler.common.type.*; 035import com.oracle.graal.graph.*; 036import com.oracle.graal.graphbuilderconf.*; 037import com.oracle.graal.jtt.*; 038import com.oracle.graal.nodeinfo.*; 039import com.oracle.graal.nodes.*; 040import com.oracle.graal.nodes.spi.*; 041 042/** 043 * Base class for LIR tests. 044 * <p> 045 * It provides facilities to replace methods with {@link LIRTestSpecification arbitrary LIR 046 * instructions}. 047 */ 048public abstract class LIRTest extends JTTTest { 049 050 @NodeInfo 051 private static final class LIRTestNode extends FixedWithNextNode implements LIRLowerable { 052 053 public static final NodeClass<LIRTestNode> TYPE = NodeClass.create(LIRTestNode.class); 054 @Input protected ValueNode opsNode; 055 @Input protected NodeInputList<ValueNode> values; 056 public final SnippetReflectionProvider snippetReflection; 057 058 public LIRTestNode(SnippetReflectionProvider snippetReflection, Kind kind, ValueNode opsNode, ValueNode[] values) { 059 super(TYPE, StampFactory.forKind(kind)); 060 this.opsNode = opsNode; 061 this.values = new NodeInputList<>(this, values); 062 this.snippetReflection = snippetReflection; 063 } 064 065 public NodeInputList<ValueNode> values() { 066 return values; 067 } 068 069 public ValueNode getLIROpsNode() { 070 return opsNode; 071 } 072 073 @Override 074 public void generate(NodeLIRBuilderTool gen) { 075 LIRTestSpecification ops = getLIROperations(); 076 Stream<Value> v = values().stream().map(node -> gen.operand(node)); 077 078 ops.generate(gen.getLIRGeneratorTool(), v.toArray(size -> new Value[size])); 079 gen.setResult(this, ops.getResult()); 080 } 081 082 public LIRTestSpecification getLIROperations() { 083 assert getLIROpsNode().isConstant(); 084 LIRTestSpecification spec = snippetReflection.asObject(LIRTestSpecification.class, getLIROpsNode().asJavaConstant()); 085 return spec; 086 } 087 } 088 089 @NodeInfo 090 private static final class LIRValueNode extends FixedWithNextNode implements LIRLowerable { 091 092 public static final NodeClass<LIRValueNode> TYPE = NodeClass.create(LIRValueNode.class); 093 @Input protected ValueNode opsNode; 094 @Input protected ValueNode name; 095 public final SnippetReflectionProvider snippetReflection; 096 097 public LIRValueNode(SnippetReflectionProvider snippetReflection, Kind kind, ValueNode opsNode, ValueNode name) { 098 super(TYPE, StampFactory.forKind(kind)); 099 this.opsNode = opsNode; 100 this.name = name; 101 this.snippetReflection = snippetReflection; 102 } 103 104 public ValueNode getLIROpsNode() { 105 return opsNode; 106 } 107 108 @Override 109 public void generate(NodeLIRBuilderTool gen) { 110 LIRTestSpecification spec = getLIROperations(); 111 Value output = spec.getOutput(getName()); 112 gen.setResult(this, isVariable(output) ? output : gen.getLIRGeneratorTool().emitMove(output)); 113 } 114 115 private String getName() { 116 assert name.isConstant(); 117 return snippetReflection.asObject(String.class, name.asJavaConstant()); 118 } 119 120 private LIRTestSpecification getLIROperations() { 121 assert getLIROpsNode().isConstant(); 122 return snippetReflection.asObject(LIRTestSpecification.class, getLIROpsNode().asJavaConstant()); 123 } 124 125 } 126 127 private InvocationPlugin lirTestPlugin = new InvocationPlugin() { 128 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode spec) { 129 Kind returnKind = targetMethod.getSignature().getReturnKind(); 130 b.addPush(returnKind, new LIRTestNode(getSnippetReflection(), returnKind, spec, new ValueNode[]{})); 131 return true; 132 } 133 134 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode spec, ValueNode arg0) { 135 Kind returnKind = targetMethod.getSignature().getReturnKind(); 136 b.addPush(returnKind, new LIRTestNode(getSnippetReflection(), returnKind, spec, new ValueNode[]{arg0})); 137 return true; 138 } 139 140 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode spec, ValueNode arg0, ValueNode arg1) { 141 Kind returnKind = targetMethod.getSignature().getReturnKind(); 142 b.addPush(returnKind, new LIRTestNode(getSnippetReflection(), returnKind, spec, new ValueNode[]{arg0, arg1})); 143 return true; 144 } 145 146 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode spec, ValueNode arg0, ValueNode arg1, ValueNode arg2) { 147 Kind returnKind = targetMethod.getSignature().getReturnKind(); 148 b.addPush(returnKind, new LIRTestNode(getSnippetReflection(), returnKind, spec, new ValueNode[]{arg0, arg1, arg2})); 149 return true; 150 } 151 152 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode spec, ValueNode arg0, ValueNode arg1, ValueNode arg2, ValueNode arg3) { 153 Kind returnKind = targetMethod.getSignature().getReturnKind(); 154 b.addPush(returnKind, new LIRTestNode(getSnippetReflection(), returnKind, spec, new ValueNode[]{arg0, arg1, arg2, arg3})); 155 return true; 156 } 157 158 }; 159 160 @Override 161 protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) { 162 InvocationPlugins invocationPlugins = conf.getPlugins().getInvocationPlugins(); 163 164 Class<? extends LIRTest> c = getClass(); 165 for (Method m : c.getMethods()) { 166 if (m.getAnnotation(LIRIntrinsic.class) != null) { 167 assert Modifier.isStatic(m.getModifiers()); 168 Class<?>[] p = m.getParameterTypes(); 169 assert p.length > 0; 170 assert LIRTestSpecification.class.isAssignableFrom(p[0]); 171 172 invocationPlugins.register(lirTestPlugin, c, m.getName(), p); 173 } 174 } 175 InvocationPlugin outputPlugin = new InvocationPlugin() { 176 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode spec, ValueNode name, ValueNode expected) { 177 Kind returnKind = targetMethod.getSignature().getReturnKind(); 178 b.addPush(returnKind, new LIRValueNode(getSnippetReflection(), returnKind, spec, name)); 179 return true; 180 } 181 }; 182 invocationPlugins.register(outputPlugin, LIRTest.class, "getOutput", new Class<?>[]{LIRTestSpecification.class, String.class, Object.class}); 183 invocationPlugins.register(outputPlugin, LIRTest.class, "getOutput", new Class<?>[]{LIRTestSpecification.class, String.class, int.class}); 184 return super.editGraphBuilderConfiguration(conf); 185 } 186 187 @SuppressWarnings("unused") 188 public static byte getOutput(LIRTestSpecification spec, String name, byte expected) { 189 return expected; 190 } 191 192 @SuppressWarnings("unused") 193 public static short getOutput(LIRTestSpecification spec, String name, short expected) { 194 return expected; 195 } 196 197 @SuppressWarnings("unused") 198 public static int getOutput(LIRTestSpecification spec, String name, int expected) { 199 return expected; 200 } 201 202 @SuppressWarnings("unused") 203 public static long getOutput(LIRTestSpecification spec, String name, long expected) { 204 return expected; 205 } 206 207 @SuppressWarnings("unused") 208 public static float getOutput(LIRTestSpecification spec, String name, float expected) { 209 return expected; 210 } 211 212 @SuppressWarnings("unused") 213 public static double getOutput(LIRTestSpecification spec, String name, double expected) { 214 return expected; 215 } 216 217 @SuppressWarnings("unused") 218 public static Object getOutput(LIRTestSpecification spec, String name, Object expected) { 219 return expected; 220 } 221 222 @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) 223 @java.lang.annotation.Target(ElementType.METHOD) 224 public static @interface LIRIntrinsic { 225 } 226 227}