1/*
2 * Copyright (c) 2011, 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 */
23package org.graalvm.compiler.lir;
24
25import static jdk.vm.ci.code.ValueUtil.asRegister;
26import static jdk.vm.ci.code.ValueUtil.isRegister;
27
28import java.util.ArrayList;
29import java.util.List;
30
31import jdk.vm.ci.code.Register;
32import jdk.vm.ci.code.RegisterValue;
33import jdk.vm.ci.code.StackSlot;
34import jdk.vm.ci.meta.Constant;
35import jdk.vm.ci.meta.JavaConstant;
36import jdk.vm.ci.meta.Value;
37
38public final class LIRValueUtil {
39
40    public static boolean isVariable(Value value) {
41        assert value != null;
42        return value instanceof Variable;
43    }
44
45    public static Variable asVariable(Value value) {
46        assert value != null;
47        return (Variable) value;
48    }
49
50    public static boolean isConstantValue(Value value) {
51        assert value != null;
52        return value instanceof ConstantValue;
53    }
54
55    public static ConstantValue asConstantValue(Value value) {
56        assert value != null;
57        return (ConstantValue) value;
58    }
59
60    public static Constant asConstant(Value value) {
61        return asConstantValue(value).getConstant();
62    }
63
64    public static boolean isJavaConstant(Value value) {
65        return isConstantValue(value) && asConstantValue(value).isJavaConstant();
66    }
67
68    public static JavaConstant asJavaConstant(Value value) {
69        return asConstantValue(value).getJavaConstant();
70    }
71
72    public static boolean isStackSlotValue(Value value) {
73        assert value != null;
74        return value instanceof StackSlot || value instanceof VirtualStackSlot;
75    }
76
77    public static boolean isVirtualStackSlot(Value value) {
78        assert value != null;
79        return value instanceof VirtualStackSlot;
80    }
81
82    public static VirtualStackSlot asVirtualStackSlot(Value value) {
83        assert value != null;
84        return (VirtualStackSlot) value;
85    }
86
87    public static boolean sameRegister(Value v1, Value v2) {
88        return isRegister(v1) && isRegister(v2) && asRegister(v1).equals(asRegister(v2));
89    }
90
91    public static boolean sameRegister(Value v1, Value v2, Value v3) {
92        return sameRegister(v1, v2) && sameRegister(v1, v3);
93    }
94
95    /**
96     * Checks if all the provided values are different physical registers. The parameters can be
97     * either {@link Register registers}, {@link Value values} or arrays of them. All values that
98     * are not {@link RegisterValue registers} are ignored.
99     */
100    public static boolean differentRegisters(Object... values) {
101        List<Register> registers = collectRegisters(values, new ArrayList<Register>());
102        for (int i = 1; i < registers.size(); i++) {
103            Register r1 = registers.get(i);
104            for (int j = 0; j < i; j++) {
105                Register r2 = registers.get(j);
106                if (r1.equals(r2)) {
107                    return false;
108                }
109            }
110        }
111        return true;
112    }
113
114    private static List<Register> collectRegisters(Object[] values, List<Register> registers) {
115        for (Object o : values) {
116            if (o instanceof Register) {
117                registers.add((Register) o);
118            } else if (o instanceof Value) {
119                if (isRegister((Value) o)) {
120                    registers.add(asRegister((Value) o));
121                }
122            } else if (o instanceof Object[]) {
123                collectRegisters((Object[]) o, registers);
124            } else {
125                throw new IllegalArgumentException("Not a Register or Value: " + o);
126            }
127        }
128        return registers;
129    }
130
131    /**
132     * Subtract sets of registers (x - y).
133     *
134     * @param x a set of register to subtract from.
135     * @param y a set of registers to subtract.
136     * @return resulting set of registers (x - y).
137     */
138    public static Value[] subtractRegisters(Value[] x, Value[] y) {
139        ArrayList<Value> result = new ArrayList<>(x.length);
140        for (Value i : x) {
141            boolean append = true;
142            for (Value j : y) {
143                if (sameRegister(i, j)) {
144                    append = false;
145                    break;
146                }
147            }
148            if (append) {
149                result.add(i);
150            }
151        }
152        Value[] resultArray = new Value[result.size()];
153        return result.toArray(resultArray);
154    }
155}
156