view graal/com.oracle.max.cri/src/com/sun/cri/ci/CiCalleeSaveLayout.java @ 4181:319860ae697a

Simplify FrameMap: make offsets of spill slots and outgoing parameters independent so that they can be allocated at the same time, eliminating the separate phases. This makes the separate StackBlock unnecesary. Change CiStackSlot to use byte offsets instead of spill slot index. This makes CiTarget.spillSlotSize unnecessary.
author Christian Wimmer <Christian.Wimmer@Oracle.com>
date Mon, 02 Jan 2012 14:16:08 -0800
parents bc8527f3071c
children
line wrap: on
line source

/*
 * Copyright (c) 2010, 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.cri.ci;

import java.util.*;


/**
 * The callee save area (CSA) is a contiguous space in a stack frame
 * used to save (and restore) the values of the caller's registers.
 * This class describes the layout of a CSA in terms of its
 * {@linkplain #size size}, {@linkplain #slotSize slot size} and
 * the {@linkplain #registers callee save registers} covered by the CSA.
 */
public class CiCalleeSaveLayout {

    /**
     * The size (in bytes) of the CSA.
     */
    public final int size;

    /**
     * The size (in bytes) of an {@linkplain #registerAtIndex(int) indexable} slot in the CSA.
     */
    public final int slotSize;

    /**
     * Map from {@linkplain CiRegister#number register numbers} to slot indexes in the CSA.
     */
    private final int[] regNumToIndex;

    private final CiRegister[] indexToReg;

    /**
     * The list of registers {@linkplain #contains(CiRegister) contained} by this CSA.
     */
    public final CiRegister[] registers;

    /**
     * The offset from the frame pointer to the CSA. If this is not known, then this field
     * will have the value {@link Integer#MAX_VALUE}.
     */
    public final int frameOffsetToCSA;

    /**
     * Creates a CSA layout.
     *
     * @param size size (in bytes) of the CSA. If this is {@code -1}, then the CSA size will be computed from {@code registers}.
     * @param slotSize the size (in bytes) of an {@linkplain #registerAtIndex(int) indexable} slot in the CSA
     * @param registers the registers that can be saved in the CSA
     */
    public CiCalleeSaveLayout(int frameOffsetToCSA, int size, int slotSize, CiRegister... registers) {
        this.frameOffsetToCSA = frameOffsetToCSA;
        assert slotSize == 0 || CiUtil.isPowerOf2(slotSize);
        this.slotSize = slotSize;
        int maxRegNum = -1;
        int maxOffset = 0;
        this.registers = registers;
        int offset = 0;
        for (CiRegister reg : registers) {
            assert offset % slotSize == 0;
            assert reg.number >= 0;
            if (reg.number > maxRegNum) {
                maxRegNum = reg.number;
            }
            if (offset > maxOffset) {
                maxOffset = offset;
            }
            offset += reg.spillSlotSize;
        }
        if (size == -1) {
            this.size = offset;
        } else {
            assert offset <= size;
            this.size = size;
        }

        this.regNumToIndex = new int[maxRegNum + 1];
        this.indexToReg = offset == 0 ? new CiRegister[0] : new CiRegister[offset / slotSize];
        Arrays.fill(regNumToIndex, -1);
        offset = 0;
        for (CiRegister reg : registers) {
            int index = offset / slotSize;
            regNumToIndex[reg.number] = index;
            indexToReg[index] = reg;
            offset += reg.spillSlotSize;
        }
    }

    /**
     * Gets the offset of a given register in the CSA.
     *
     * @return the offset (in bytes) of {@code reg} in the CSA
     * @throws IllegalArgumentException if {@code reg} does not have a slot in the CSA
     */
    public int offsetOf(int reg) {
        return indexOf(reg) * slotSize;
    }

    /**
     * Gets the index of a given register in the CSA.
     *
     * @return the index of {@code reg} in the CSA
     * @throws IllegalArgumentException if {@code reg} does not have a slot in the CSA
     */
    public int indexOf(int reg) {
        if (!contains(reg)) {
            throw new IllegalArgumentException(String.valueOf(reg));
        }
        return regNumToIndex[reg];
    }

    /**
     * Gets the offset of a given register in the CSA.
     *
     * @return the offset (in bytes) of {@code reg} in the CSA
     * @throws IllegalArgumentException if {@code reg} does not have a slot in the CSA
     */
    public int offsetOf(CiRegister reg) {
        return offsetOf(reg.number);
    }

    /**
     * Determines if the CSA includes a slot for a given register.
     *
     * @param reg the register to test
     * @return true if the CSA contains a slot for {@code reg}
     */
    public boolean contains(int reg) {
        return reg >= 0 && reg < regNumToIndex.length && regNumToIndex[reg] != -1;
    }

    /**
     * Gets the register whose slot in the CSA is at a given index.
     *
     * @param index an index of a slot in the CSA
     * @return the register whose slot in the CSA is at  {@code index} or {@code null} if {@code index} does not denote a
     *         slot in the CSA aligned with a register
     */
    public CiRegister registerAt(int index) {
        if (index < 0 || index >= indexToReg.length) {
            return null;
        }
        return indexToReg[index];
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[");
        for (CiRegister reg : registers) {
            if (sb.length() != 1) {
                sb.append(", ");
            }
            sb.append(reg).append("{+").append(offsetOf(reg)).append('}');
        }
        return sb.append("] size=").append(size).toString();
    }
}