Mercurial > hg > graal-compiler
diff graal/com.oracle.jvmci.code/src/com/oracle/jvmci/code/CalleeSaveLayout.java @ 21556:48c1ebd24120
renamed com.oracle.graal.api[meta|code] modules to com.oracle.jvmci.[meta|code] (JBS:GRAAL-53)
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Wed, 27 May 2015 00:36:16 +0200 |
parents | graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CalleeSaveLayout.java@1cde96b96673 |
children | f5b549811bac |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.jvmci.code/src/com/oracle/jvmci/code/CalleeSaveLayout.java Wed May 27 00:36:16 2015 +0200 @@ -0,0 +1,182 @@ +/* + * 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.oracle.jvmci.code; + +import com.oracle.jvmci.meta.PlatformKind; +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 CalleeSaveLayout { + + /** + * The size (in bytes) of the CSA. + */ + public final int size; + + /** + * The size (in bytes) of an {@linkplain #registerAt(int) indexable} slot in the CSA. + */ + public final int slotSize; + + /** + * Map from {@linkplain Register#number register numbers} to slot indexes in the CSA. + */ + private final int[] regNumToIndex; + + private final Register[] indexToReg; + + /** + * The list of registers {@linkplain #contains(int) contained} by this CSA. + */ + public final Register[] 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 #registerAt(int) indexable} slot in the + * CSA + * @param registers the registers that can be saved in the CSA + */ + public CalleeSaveLayout(TargetDescription target, int frameOffsetToCSA, int size, int slotSize, Register... registers) { + this.frameOffsetToCSA = frameOffsetToCSA; + assert slotSize == 0 || CodeUtil.isPowerOf2(slotSize); + this.slotSize = slotSize; + int maxRegNum = -1; + int maxOffset = 0; + this.registers = registers; + int offset = 0; + for (Register reg : registers) { + assert offset % slotSize == 0; + assert reg.number >= 0; + if (reg.number > maxRegNum) { + maxRegNum = reg.number; + } + if (offset > maxOffset) { + maxOffset = offset; + } + PlatformKind kind = target.arch.getLargestStorableKind(reg.getRegisterCategory()); + offset += target.getSizeInBytes(kind); + } + if (size == -1) { + this.size = offset; + } else { + assert offset <= size; + this.size = size; + } + + this.regNumToIndex = new int[maxRegNum + 1]; + this.indexToReg = offset == 0 ? new Register[0] : new Register[offset / slotSize]; + Arrays.fill(regNumToIndex, -1); + offset = 0; + for (Register reg : registers) { + int index = offset / slotSize; + regNumToIndex[reg.number] = index; + indexToReg[index] = reg; + PlatformKind kind = target.arch.getLargestStorableKind(reg.getRegisterCategory()); + offset += target.getSizeInBytes(kind); + } + } + + /** + * 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(Register 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 Register registerAt(int index) { + if (index < 0 || index >= indexToReg.length) { + return null; + } + return indexToReg[index]; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("["); + for (Register reg : registers) { + if (sb.length() != 1) { + sb.append(", "); + } + sb.append(reg).append("{+").append(offsetOf(reg)).append('}'); + } + return sb.append("] size=").append(size).toString(); + } +}