Mercurial > hg > truffle
view graal/com.oracle.max.asmdis/src/com/sun/max/asm/gen/InstructionConstraint.java @ 4205:2af849af1723
moved graphbuilder into the graal.java project.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Tue, 03 Jan 2012 18:22:10 +0100 |
parents | e233f5660da4 |
children |
line wrap: on
line source
/* * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.max.asm.gen; import java.lang.reflect.*; import java.util.*; import com.sun.max.*; import com.sun.max.asm.*; import com.sun.max.program.*; /** * An instruction constraint can be specified as part of an {@link InstructionDescription} to specify a constraint on one * or more parameters of the assembler method that will be generated from the instruction description. * <p> * An instruction constraint implements a predicate on a complete assembler instruction and it's used by the * {@link AssemblyTester test framework} in concert with {@link Parameter#getLegalTestArguments()} to generate test * cases. */ public interface InstructionConstraint { /** * Determines if a given set of parameter bindings (i.e. arguments) for an assembler method is valid. * * @param template an instruction template * @param arguments the list of arguments to check * @return true if the argument list is valid, false otherwise */ boolean check(Template template, List<Argument> arguments); /** * @return a Java expression that performs the {@link #check check} */ String asJavaExpression(); /** * Determines if this constraint has {@code parameter} as one of its terms. */ boolean referencesParameter(Parameter parameter); /** * Gets the method that implements the predicate of the constraint. * * @return {@code null} if this is a simple expression constraint */ Method predicateMethod(); public abstract static class SimpleInstructionConstraint implements InstructionConstraint { public Method predicateMethod() { return null; } @Override public String toString() { return asJavaExpression(); } } public static final class Static { private Static() { } /** * Creates an instruction constraint on a parameter such that it must be a given symbol. */ public static InstructionConstraint eq(final Parameter first, final SymbolicArgument symbol) { return new SimpleInstructionConstraint() { public boolean check(Template template, List<Argument> arguments) { return template.bindingFor(first, arguments) == symbol; } public String asJavaExpression() { return first.variableName() + " == " + symbol.name(); } public boolean referencesParameter(Parameter parameter) { return parameter == first; } }; } /** * Creates an instruction constraint between two parameters such that their values cannot be the same. */ public static InstructionConstraint ne(final Parameter first, final Parameter second) { return new SimpleInstructionConstraint() { public boolean check(Template template, List<Argument> arguments) { return template.bindingFor(first, arguments).asLong() != template.bindingFor(second, arguments).asLong(); } public String asJavaExpression() { return first.valueString() + " != " + second.valueString(); } public boolean referencesParameter(Parameter parameter) { return parameter == first || parameter == second; } }; } /** * Creates an instruction constraint on a parameter such that it must not be a given symbol. */ public static InstructionConstraint ne(final Parameter first, final SymbolicArgument symbol) { return new SimpleInstructionConstraint() { public boolean check(Template template, List<Argument> arguments) { return template.bindingFor(first, arguments) != symbol; } public String asJavaExpression() { return first.variableName() + " != " + symbol.name(); } public boolean referencesParameter(Parameter parameter) { return parameter == first; } }; } /** * Creates an instruction constraint between two parameters such that the value of the first parameter must be * less than the value of the second. */ public static InstructionConstraint lt(final Parameter first, final Parameter second) { return new SimpleInstructionConstraint() { public boolean check(Template template, List<Argument> arguments) { return template.bindingFor(first, arguments).asLong() < template.bindingFor(second, arguments).asLong(); } public String asJavaExpression() { return first.valueString() + " < " + second.valueString(); } public boolean referencesParameter(Parameter parameter) { return parameter == first || parameter == second; } }; } /** * Creates an instruction constraint between two parameters such that the value of the first parameter must be * less than or equal to the value of the second. */ public static InstructionConstraint le(final Parameter first, final Parameter second) { return new SimpleInstructionConstraint() { public boolean check(Template template, List<Argument> arguments) { return template.bindingFor(first, arguments).asLong() <= template.bindingFor(second, arguments).asLong(); } public String asJavaExpression() { return first.valueString() + " <= " + second.valueString(); } public boolean referencesParameter(Parameter parameter) { return parameter == first || parameter == second; } }; } /** * Creates an instruction constraint on a given parameter such that its value is greater than a given value. */ public static InstructionConstraint gt(final Parameter first, final long value) { return new SimpleInstructionConstraint() { public boolean check(Template template, List<Argument> arguments) { return template.bindingFor(first, arguments).asLong() > value; } public String asJavaExpression() { return first.valueString() + " > " + value; } public boolean referencesParameter(Parameter parameter) { return parameter == first; } }; } /** * Creates an instruction constraint on a given parameter such that its value is less than a given value. */ public static InstructionConstraint lt(final Parameter first, final long value) { return new SimpleInstructionConstraint() { public boolean check(Template template, List<Argument> arguments) { return template.bindingFor(first, arguments).asLong() < value; } public String asJavaExpression() { return first.valueString() + " < " + value; } public boolean referencesParameter(Parameter parameter) { return parameter == first; } }; } /** * Creates an instruction constraint on a given parameter such that its value must not be equal to a given value. */ public static InstructionConstraint ne(final Parameter parameter, final long value) { return new SimpleInstructionConstraint() { public boolean check(Template template, List<Argument> arguments) { return template.bindingFor(parameter, arguments).asLong() != value; } public String asJavaExpression() { return parameter.valueString() + " != " + value; } public boolean referencesParameter(Parameter p) { return parameter == p; } }; } /** * Creates an instruction constraint on a given parameter such that its value must be even. */ public static InstructionConstraint even(final Parameter parameter) { return new SimpleInstructionConstraint() { public boolean check(Template template, List<Argument> arguments) { return template.bindingFor(parameter, arguments).asLong() % 2 == 0; } public String asJavaExpression() { return "(" + parameter.valueString() + " % 2) == 0"; } public boolean referencesParameter(Parameter p) { return parameter == p; } }; } /** * Gets a reference to a Java method that returns a boolean. This is a convenience wrapper for * {@link Class#getDeclaredMethod} that converts the checked {@link NoSuchMethodException} into a * {@link ProgramError}. * * The method must have a boolean return type and only accept parameter types corresponding to the unboxed types * of a generated assembler method. */ public static Method getPredicateMethod(Class<?> declaringClass, String methodName, Class... parameterTypes) { try { return declaringClass.getDeclaredMethod(methodName, parameterTypes); } catch (NoSuchMethodException e) { throw ProgramError.unexpected("constraint method not found: " + declaringClass + "." + methodName + "(" + Utils.toString(parameterTypes, ", ") + ")"); } } /** * Creates an instruction constraint implemented by a Java method. * * @param predicateMethod * the constraint checking method which must have a {@code boolean} return type * @param parameters * the formal parameters of the assembler method whose values are constrained by {@code method}. * There must be one element in this list for each formal parameter of {@code method} * including one for the receiver if {@code method} is not static. The binding between the two * is by position. */ public static InstructionConstraint makePredicate(final Method predicateMethod, final Parameter... parameters) throws IllegalArgumentException { ProgramError.check(predicateMethod.getReturnType() == Boolean.TYPE, "predicate method must return a boolean"); final boolean isStatic = Modifier.isStatic(predicateMethod.getModifiers()); ProgramError.check(predicateMethod.getParameterTypes().length == (isStatic ? parameters.length : parameters.length - 1), "parameter count != method "); return new InstructionConstraint() { /** * @return the method implementing the constraint */ public Method predicateMethod() { return predicateMethod; } /** * Determines if the constraint holds for a given set of actual values to a given assembler method. * * @param template * the template from which the assembler method was generated * @param arguments * the actual values * @return true if the constraint held for {@code arguments} */ public boolean check(Template template, List<Argument> arguments) { int parameterIndex; final Object receiver; final Object[] objects; if (isStatic) { parameterIndex = 0; receiver = null; objects = new Object[parameters.length]; } else { parameterIndex = 1; objects = new Object[parameters.length - 1]; receiver = template.bindingFor(parameters[0], arguments); } for (int i = 0; i != objects.length; ++i, ++parameterIndex) { final Parameter parameter = parameters[parameterIndex]; final Argument argument = template.bindingFor(parameter, arguments); objects[i] = (argument instanceof ImmediateArgument) ? ((ImmediateArgument) argument).boxedJavaValue() : argument; } try { return (Boolean) predicateMethod.invoke(receiver, objects); } catch (IllegalArgumentException illegalArgumentException) { throw ProgramError.unexpected("argument type mismatch", illegalArgumentException); } catch (IllegalAccessException illegalAccessException) { throw ProgramError.unexpected("illegal access to predicate method unexpected", illegalAccessException); } catch (InvocationTargetException invocationTargetException) { throw ProgramError.unexpected(invocationTargetException); } } /** * @return the Java boolean expression that is a call to the constraint method */ public String asJavaExpression() { final StringBuilder buf = new StringBuilder(); int i; if (isStatic) { buf.append(predicateMethod.getDeclaringClass().getSimpleName()); i = 0; } else { buf.append(parameters[0].variableName()); i = 1; } buf.append('.').append(predicateMethod.getName()).append('('); while (i < parameters.length) { final Parameter parameter = parameters[i]; buf.append(parameter.variableName()); if (i != parameters.length - 1) { buf.append(", "); } ++i; } buf.append(')'); return buf.toString(); } public boolean referencesParameter(Parameter parameter) { return Utils.indexOfIdentical(parameters, parameter) >= 0; } }; } } }