001/*
002 * Copyright (c) 2013, 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.lir;
024
025import java.lang.annotation.*;
026import java.util.*;
027
028import com.oracle.graal.debug.*;
029import jdk.internal.jvmci.meta.*;
030
031import com.oracle.graal.lir.LIRInstruction.OperandFlag;
032import com.oracle.graal.lir.LIRInstruction.OperandMode;
033
034/**
035 * Base class to represent values that need to be stored in more than one register. This is mainly
036 * intended to support addresses and not general arbitrary nesting of composite values. Because of
037 * the possibility of sharing of CompositeValues they should be immutable.
038 */
039public abstract class CompositeValue extends AbstractValue {
040
041    @Retention(RetentionPolicy.RUNTIME)
042    @Target(ElementType.FIELD)
043    public static @interface Component {
044
045        OperandFlag[] value() default OperandFlag.REG;
046    }
047
048    private static final DebugMetric COMPOSITE_VALUE_COUNT = Debug.metric("CompositeValues");
049
050    public CompositeValue(LIRKind kind) {
051        super(kind);
052        COMPOSITE_VALUE_COUNT.increment();
053        assert CompositeValueClass.get(getClass()) != null;
054    }
055
056    /**
057     * Invoke {@code proc} on each {@link Value} element of this {@link CompositeValue}. If
058     * {@code proc} replaces any value then a new CompositeValue should be returned.
059     *
060     * @param inst
061     * @param mode
062     * @param proc
063     * @return the original CompositeValue or a copy with any modified values
064     */
065    public abstract CompositeValue forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc);
066
067    /**
068     * A helper method to visit {@link Value}[] ensuring that a copy of the array is made if it's
069     * needed.
070     *
071     * @param inst
072     * @param values
073     * @param mode
074     * @param proc
075     * @param flags
076     * @return the original {@code values} array or a copy if values changed
077     */
078    protected Value[] visitValueArray(LIRInstruction inst, Value[] values, OperandMode mode, InstructionValueProcedure proc, EnumSet<OperandFlag> flags) {
079        Value[] newValues = null;
080        for (int i = 0; i < values.length; i++) {
081            Value value = values[i];
082            Value newValue = proc.doValue(inst, value, mode, flags);
083            if (!value.identityEquals(newValue)) {
084                if (newValues == null) {
085                    newValues = values.clone();
086                }
087                newValues[i] = value;
088            }
089        }
090        return newValues != null ? newValues : values;
091    }
092
093    protected abstract void forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueConsumer proc);
094
095    @Override
096    public String toString() {
097        return CompositeValueClass.format(this);
098    }
099
100    @Override
101    public int hashCode() {
102        return 53 * super.hashCode();
103    }
104
105    @Override
106    public boolean equals(Object obj) {
107        if (obj instanceof CompositeValue) {
108            CompositeValue other = (CompositeValue) obj;
109            return super.equals(other);
110        }
111        return false;
112    }
113}