Mercurial > hg > truffle
view graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchPattern.java @ 15370:319deee16746
add support for matching multiple HIR nodes when lowering to LIR
author | Tom Rodriguez <tom.rodriguez@oracle.com> |
---|---|
date | Thu, 24 Apr 2014 12:00:54 -0700 |
parents | |
children | 100306ae985b |
line wrap: on
line source
/* * Copyright (c) 2014, 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.oracle.graal.compiler.match; import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.nodes.*; /** * A simple recursive pattern matcher for a DAG of nodes. */ public class MatchPattern { enum MatchResultCode { OK, WRONG_CLASS, NAMED_VALUE_MISMATCH, TOO_MANY_USERS, NOT_IN_BLOCK, NOT_SAFE, ALREADY_USED, } /** * A descriptive result for match failures. This can be helpful for debugging why a match * doesn't work as expected. */ static class Result { final MatchResultCode code; final ScheduledNode node; final MatchPattern matcher; Result(MatchResultCode result, ScheduledNode node, MatchPattern matcher) { this.code = result; this.node = node; this.matcher = matcher; } static final Result OK = new Result(MatchResultCode.OK, null, null); static Result WRONG_CLASS(ValueNode node, MatchPattern matcher) { return new Result(MatchResultCode.WRONG_CLASS, node, matcher); } static Result NAMED_VALUE_MISMATCH(ValueNode node, MatchPattern matcher) { return new Result(MatchResultCode.NAMED_VALUE_MISMATCH, node, matcher); } static Result TOO_MANY_USERS(ValueNode node, MatchPattern matcher) { return new Result(MatchResultCode.TOO_MANY_USERS, node, matcher); } static Result NOT_IN_BLOCK(ScheduledNode node, MatchPattern matcher) { return new Result(MatchResultCode.NOT_IN_BLOCK, node, matcher); } static Result NOT_SAFE(ScheduledNode node, MatchPattern matcher) { return new Result(MatchResultCode.NOT_SAFE, node, matcher); } static Result ALREADY_USED(ValueNode node, MatchPattern matcher) { return new Result(MatchResultCode.ALREADY_USED, node, matcher); } @Override public String toString() { if (code == MatchResultCode.OK) { return "OK"; } return code + " " + node.toString(Verbosity.Id) + "|" + node.getClass().getSimpleName() + " " + matcher; } } /** * The expected type of the node. It must match exactly. */ private final Class<? extends ValueNode> nodeClass; /** * An optional name for this node. A name can occur multiple times in a match and that name must * always refer to the same node of the match will fail. */ private final String name; /** * An optional pattern for the first input. */ private final MatchPattern first; /** * An optional pattern for the second input. */ private final MatchPattern second; /** * Helper class to visit the inputs. */ private final MatchNodeAdapter adapter; /** * Can there only be one user of the node. Constant nodes can be matched even if there are other * users. */ private final boolean singleUser; public MatchPattern(String name, boolean singleUser) { this(null, name, null, null, null, singleUser); } public MatchPattern(Class<? extends ValueNode> nodeClass, String name, boolean singleUser) { this(nodeClass, name, null, null, null, singleUser); } public MatchPattern(Class<? extends ValueNode> nodeClass, String name, MatchPattern first, MatchNodeAdapter adapter, boolean singleUser) { this(nodeClass, name, first, null, adapter, singleUser); } public MatchPattern(Class<? extends ValueNode> nodeClass, String name, MatchPattern first, MatchPattern second, MatchNodeAdapter adapter, boolean singleUser) { this.nodeClass = nodeClass; this.name = name; this.singleUser = singleUser; this.first = first; this.second = second; this.adapter = adapter; } Class<? extends ValueNode> nodeClass() { return nodeClass; } Result match(ValueNode node, MatchContext context) { return matchTree(node, context, true); } private Result matchTree(ValueNode node, MatchContext context, boolean atRoot) { Result result = Result.OK; if (nodeClass != null && node.getClass() != nodeClass) { return Result.WRONG_CLASS(node, this); } if (singleUser && !atRoot) { result = context.consume(node); if (result != Result.OK) { return result; } } if (name != null) { result = context.captureNamedValue(name, nodeClass, node); } if (first != null) { result = first.matchTree(adapter.getFirstInput(node), context, false); if (result == Result.OK && second != null) { result = second.matchTree(adapter.getSecondInput(node), context, false); } } return result; } /** * For a node starting at root, produce a String showing the inputs that matched against this * rule. It's assumed that a match has already succeeded against this rule, otherwise the * printing may produce exceptions. */ public String formatMatch(ValueNode root) { String result = String.format("%s", root); if (first == null && second == null) { return result; } else { return "(" + result + (first != null ? " " + first.formatMatch(adapter.getFirstInput(root)) : "") + (second != null ? " " + second.formatMatch(adapter.getSecondInput(root)) : "") + ")"; } } @Override public String toString() { if (nodeClass == null) { return name; } else { String pre = first != null || second != null ? "(" : ""; String post = first != null || second != null ? ")" : ""; String nodeName = nodeClass.getSimpleName(); return pre + nodeName + (name != null ? "=\"" + name + "\"" : "") + (first != null ? (" " + first.toString()) : "") + (second != null ? (" " + second.toString()) : "") + post; } } }