001/* 002 * Copyright (c) 2010, 2011, 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 jdk.internal.jvmci.code; 024 025import java.util.*; 026 027import jdk.internal.jvmci.meta.*; 028 029/** 030 * The callee save area (CSA) is a contiguous space in a stack frame used to save (and restore) the 031 * values of the caller's registers. This class describes the layout of a CSA in terms of its 032 * {@linkplain #size size}, {@linkplain #slotSize slot size} and the {@linkplain #registers callee 033 * save registers} covered by the CSA. 034 */ 035public class CalleeSaveLayout { 036 037 /** 038 * The size (in bytes) of the CSA. 039 */ 040 public final int size; 041 042 /** 043 * The size (in bytes) of an {@linkplain #registerAt(int) indexable} slot in the CSA. 044 */ 045 public final int slotSize; 046 047 /** 048 * Map from {@linkplain Register#number register numbers} to slot indexes in the CSA. 049 */ 050 private final int[] regNumToIndex; 051 052 private final Register[] indexToReg; 053 054 /** 055 * The list of registers {@linkplain #contains(int) contained} by this CSA. 056 */ 057 public final Register[] registers; 058 059 /** 060 * The offset from the frame pointer to the CSA. If this is not known, then this field will have 061 * the value {@link Integer#MAX_VALUE}. 062 */ 063 public final int frameOffsetToCSA; 064 065 /** 066 * Creates a CSA layout. 067 * 068 * @param size size (in bytes) of the CSA. If this is {@code -1}, then the CSA size will be 069 * computed from {@code registers}. 070 * @param slotSize the size (in bytes) of an {@linkplain #registerAt(int) indexable} slot in the 071 * CSA 072 * @param registers the registers that can be saved in the CSA 073 */ 074 public CalleeSaveLayout(TargetDescription target, int frameOffsetToCSA, int size, int slotSize, Register... registers) { 075 this.frameOffsetToCSA = frameOffsetToCSA; 076 assert slotSize == 0 || CodeUtil.isPowerOf2(slotSize); 077 this.slotSize = slotSize; 078 int maxRegNum = -1; 079 int maxOffset = 0; 080 this.registers = registers; 081 int offset = 0; 082 for (Register reg : registers) { 083 assert offset % slotSize == 0; 084 assert reg.number >= 0; 085 if (reg.number > maxRegNum) { 086 maxRegNum = reg.number; 087 } 088 if (offset > maxOffset) { 089 maxOffset = offset; 090 } 091 PlatformKind kind = target.arch.getLargestStorableKind(reg.getRegisterCategory()); 092 offset += target.getSizeInBytes(kind); 093 } 094 if (size == -1) { 095 this.size = offset; 096 } else { 097 assert offset <= size; 098 this.size = size; 099 } 100 101 this.regNumToIndex = new int[maxRegNum + 1]; 102 this.indexToReg = offset == 0 ? new Register[0] : new Register[offset / slotSize]; 103 Arrays.fill(regNumToIndex, -1); 104 offset = 0; 105 for (Register reg : registers) { 106 int index = offset / slotSize; 107 regNumToIndex[reg.number] = index; 108 indexToReg[index] = reg; 109 PlatformKind kind = target.arch.getLargestStorableKind(reg.getRegisterCategory()); 110 offset += target.getSizeInBytes(kind); 111 } 112 } 113 114 /** 115 * Gets the offset of a given register in the CSA. 116 * 117 * @return the offset (in bytes) of {@code reg} in the CSA 118 * @throws IllegalArgumentException if {@code reg} does not have a slot in the CSA 119 */ 120 public int offsetOf(int reg) { 121 return indexOf(reg) * slotSize; 122 } 123 124 /** 125 * Gets the index of a given register in the CSA. 126 * 127 * @return the index of {@code reg} in the CSA 128 * @throws IllegalArgumentException if {@code reg} does not have a slot in the CSA 129 */ 130 public int indexOf(int reg) { 131 if (!contains(reg)) { 132 throw new IllegalArgumentException(String.valueOf(reg)); 133 } 134 return regNumToIndex[reg]; 135 } 136 137 /** 138 * Gets the offset of a given register in the CSA. 139 * 140 * @return the offset (in bytes) of {@code reg} in the CSA 141 * @throws IllegalArgumentException if {@code reg} does not have a slot in the CSA 142 */ 143 public int offsetOf(Register reg) { 144 return offsetOf(reg.number); 145 } 146 147 /** 148 * Determines if the CSA includes a slot for a given register. 149 * 150 * @param reg the register to test 151 * @return true if the CSA contains a slot for {@code reg} 152 */ 153 public boolean contains(int reg) { 154 return reg >= 0 && reg < regNumToIndex.length && regNumToIndex[reg] != -1; 155 } 156 157 /** 158 * Gets the register whose slot in the CSA is at a given index. 159 * 160 * @param index an index of a slot in the CSA 161 * @return the register whose slot in the CSA is at {@code index} or {@code null} if 162 * {@code index} does not denote a slot in the CSA aligned with a register 163 */ 164 public Register registerAt(int index) { 165 if (index < 0 || index >= indexToReg.length) { 166 return null; 167 } 168 return indexToReg[index]; 169 } 170 171 @Override 172 public String toString() { 173 StringBuilder sb = new StringBuilder("["); 174 for (Register reg : registers) { 175 if (sb.length() != 1) { 176 sb.append(", "); 177 } 178 sb.append(reg).append("{+").append(offsetOf(reg)).append('}'); 179 } 180 return sb.append("] size=").append(size).toString(); 181 } 182}