1 /*
2  * Copyright (c) 2010, 2011, 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  */
23 package jdk.vm.ci.code;
24 
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.List;
28 
29 /**
30  * A collection of register attributes. The specific attribute values for a register may be local to
31  * a compilation context. For example, a {@link RegisterConfig} in use during a compilation will
32  * determine which registers are callee saved.
33  */
34 public class RegisterAttributes {
35 
36     private final boolean callerSave;
37     private final boolean calleeSave;
38     private final boolean allocatable;
39 
RegisterAttributes(boolean isCallerSave, boolean isCalleeSave, boolean isAllocatable)40     public RegisterAttributes(boolean isCallerSave, boolean isCalleeSave, boolean isAllocatable) {
41         this.callerSave = isCallerSave;
42         this.calleeSave = isCalleeSave;
43         this.allocatable = isAllocatable;
44     }
45 
46     public static final RegisterAttributes NONE = new RegisterAttributes(false, false, false);
47 
48     /**
49      * Creates a map from register {@linkplain Register#number numbers} to register
50      * {@linkplain RegisterAttributes attributes} for a given register configuration and set of
51      * registers.
52      *
53      * @param registerConfig a register configuration
54      * @param registers a set of registers
55      * @return an array whose length is the max register number in {@code registers} plus 1. An
56      *         element at index i holds the attributes of the register whose number is i.
57      */
createMap(RegisterConfig registerConfig, RegisterArray registers)58     public static RegisterAttributes[] createMap(RegisterConfig registerConfig, RegisterArray registers) {
59         RegisterAttributes[] map = new RegisterAttributes[registers.size()];
60         List<Register> callerSaveRegisters = registerConfig.getCallerSaveRegisters().asList();
61         List<Register> calleeSaveRegisters = registerConfig.getCalleeSaveRegisters() == null ? Collections.emptyList() : registerConfig.getCalleeSaveRegisters().asList();
62         List<Register> allocatableRegisters = registerConfig.getAllocatableRegisters().asList();
63         for (Register reg : registers) {
64             if (reg != null) {
65                 RegisterAttributes attr = new RegisterAttributes(callerSaveRegisters.contains(reg), calleeSaveRegisters.contains(reg), allocatableRegisters.contains(reg));
66                 if (map.length <= reg.number) {
67                     map = Arrays.copyOf(map, reg.number + 1);
68                 }
69                 map[reg.number] = attr;
70             }
71         }
72         for (int i = 0; i < map.length; i++) {
73             if (map[i] == null) {
74                 map[i] = NONE;
75             }
76         }
77         return map;
78     }
79 
80     /**
81      * @return {@code true} if a register is available for use by a register allocator otherwise
82      *         {@code false}
83      */
isAllocatable()84     public boolean isAllocatable() {
85         return allocatable;
86     }
87 
88     /**
89      * @return {@code true} if a register whose value preservation (if required) across a call is
90      *         the responsibility of the callee otherwise {@code false}
91      */
isCalleeSave()92     public boolean isCalleeSave() {
93         return calleeSave;
94     }
95 
96     /**
97      * @return {@code true} if a register whose value preservation (if required) across a call is
98      *         the responsibility of the caller otherwise {@code false}
99      */
isCallerSave()100     public boolean isCallerSave() {
101         return callerSave;
102     }
103 }
104