001/*
002 * Copyright (c) 2014, 2014, 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.replacements.nodes;
024
025import jdk.internal.jvmci.common.*;
026
027import com.oracle.graal.compiler.common.type.*;
028import com.oracle.graal.graph.*;
029import com.oracle.graal.graph.spi.*;
030import com.oracle.graal.nodeinfo.*;
031import com.oracle.graal.nodes.*;
032import com.oracle.graal.nodes.spi.*;
033
034/**
035 * Assertion nodes will go away as soon as the value evaluates to true. Compile-time assertions will
036 * fail if this has not happened by the time the node is lowered to LIR, while runtime assertions
037 * may need to insert a check.
038 */
039@NodeInfo
040public final class AssertionNode extends FixedWithNextNode implements Lowerable, Canonicalizable, LIRLowerable {
041
042    public static final NodeClass<AssertionNode> TYPE = NodeClass.create(AssertionNode.class);
043    @Input ValueNode value;
044
045    protected final boolean compileTimeAssertion;
046    protected final String message;
047
048    public AssertionNode(boolean compileTimeAssertion, ValueNode value, String message) {
049        super(TYPE, StampFactory.forVoid());
050        this.value = value;
051        this.compileTimeAssertion = compileTimeAssertion;
052        this.message = message;
053    }
054
055    public ValueNode value() {
056        return value;
057    }
058
059    public String message() {
060        return message;
061    }
062
063    @Override
064    public Node canonical(CanonicalizerTool tool) {
065        if (value.isConstant() && value.asJavaConstant().asInt() != 0) {
066            return null;
067        }
068        /*
069         * Assertions with a constant "false" value do not immediately cause an error, since they
070         * may be unreachable and could thus be removed by later optimizations.
071         */
072        return this;
073    }
074
075    public void lower(LoweringTool tool) {
076        if (!compileTimeAssertion) {
077            tool.getLowerer().lower(this, tool);
078        }
079    }
080
081    public void generate(NodeLIRBuilderTool generator) {
082        assert compileTimeAssertion;
083        if (value.isConstant()) {
084            if (value.asJavaConstant().asInt() == 0) {
085                throw new JVMCIError("%s: failed compile-time assertion: %s", this, message);
086            }
087        } else {
088            throw new JVMCIError("%s: failed compile-time assertion (value %s): %s", this, value, message);
089        }
090    }
091
092    @NodeIntrinsic
093    public static native void assertion(@ConstantNodeParameter boolean compileTimeAssertion, boolean value, @ConstantNodeParameter String message);
094}