Mercurial > hg > graal-compiler
comparison graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiAddress.java @ 4314:9ce8594bedaf
Allow CiAddress as Input and Alive operands of LIR instructions.
author | Christian Wimmer <Christian.Wimmer@Oracle.com> |
---|---|
date | Thu, 19 Jan 2012 14:14:36 -0800 |
parents | 430b5db3e6f8 |
children | 438ab53efdd0 |
comparison
equal
deleted
inserted
replaced
4313:79af35bd9fd7 | 4314:9ce8594bedaf |
---|---|
24 | 24 |
25 import static com.oracle.max.cri.ci.CiValueUtil.*; | 25 import static com.oracle.max.cri.ci.CiValueUtil.*; |
26 | 26 |
27 /** | 27 /** |
28 * Represents an address in target machine memory, specified via some combination of a base register, an index register, | 28 * Represents an address in target machine memory, specified via some combination of a base register, an index register, |
29 * a displacement and a scale. Note that the base and index registers may be {@link CiVariable variable}, that is as yet | 29 * a displacement and a scale. Note that the base and index registers may be a variable that will get a register assigned |
30 * unassigned to target machine registers. | 30 * later by the register allocator. |
31 */ | 31 */ |
32 public final class CiAddress extends CiValue { | 32 public final class CiAddress extends CiValue { |
33 private static final long serialVersionUID = -1003772042519945089L; | 33 private static final long serialVersionUID = -1003772042519945089L; |
34 | 34 |
35 /** | 35 /** |
36 * A sentinel value used as a place holder in an instruction stream for an address that will be patched. | 36 * A sentinel value used as a place holder in an instruction stream for an address that will be patched. |
37 */ | 37 */ |
38 public static final CiAddress Placeholder = new CiAddress(CiKind.Illegal, CiValue.IllegalValue); | 38 public static final CiAddress Placeholder = new CiAddress(CiKind.Illegal, CiValue.IllegalValue); |
39 | 39 |
40 /** | 40 /** |
41 * Base register that defines the start of the address computation; always present. | 41 * Base register that defines the start of the address computation. |
42 */ | |
43 public final CiValue base; | |
44 /** | |
45 * Optional index register, the value of which (possibly scaled by {@link #scale}) is added to {@link #base}. | |
46 * If not present, is denoted by {@link CiValue#IllegalValue}. | 42 * If not present, is denoted by {@link CiValue#IllegalValue}. |
47 */ | 43 */ |
48 public final CiValue index; | 44 public CiValue base; |
45 | |
46 /** | |
47 * Index register, the value of which (possibly scaled by {@link #scale}) is added to {@link #base}. | |
48 * If not present, is denoted by {@link CiValue#IllegalValue}. | |
49 */ | |
50 public CiValue index; | |
51 | |
49 /** | 52 /** |
50 * Scaling factor for indexing, dependent on target operand size. | 53 * Scaling factor for indexing, dependent on target operand size. |
51 */ | 54 */ |
52 public final Scale scale; | 55 public final Scale scale; |
56 | |
53 /** | 57 /** |
54 * Optional additive displacement. | 58 * Optional additive displacement. |
55 */ | 59 */ |
56 public final int displacement; | 60 public final int displacement; |
57 | 61 |
73 public CiAddress(CiKind kind, CiValue base, int displacement) { | 77 public CiAddress(CiKind kind, CiValue base, int displacement) { |
74 this(kind, base, IllegalValue, Scale.Times1, displacement); | 78 this(kind, base, IllegalValue, Scale.Times1, displacement); |
75 } | 79 } |
76 | 80 |
77 /** | 81 /** |
78 * Creates a {@code CiAddress} with given base and offset registers, no scaling and no displacement. | |
79 * @param kind the kind of the value being addressed | |
80 * @param base the base register | |
81 * @param offset the offset register | |
82 */ | |
83 public CiAddress(CiKind kind, CiValue base, CiValue offset) { | |
84 this(kind, base, offset, Scale.Times1, 0); | |
85 } | |
86 | |
87 /** | |
88 * Creates a {@code CiAddress} with given base and index registers, scaling and displacement. | 82 * Creates a {@code CiAddress} with given base and index registers, scaling and displacement. |
89 * This is the most general constructor.. | 83 * This is the most general constructor.. |
90 * @param kind the kind of the value being addressed | 84 * @param kind the kind of the value being addressed |
91 * @param base the base register | 85 * @param base the base register |
92 * @param index the index register | 86 * @param index the index register |
93 * @param scale the scaling factor | 87 * @param scale the scaling factor |
94 * @param displacement the displacement | 88 * @param displacement the displacement |
95 */ | 89 */ |
96 public CiAddress(CiKind kind, CiValue base, CiValue index, Scale scale, int displacement) { | 90 public CiAddress(CiKind kind, CiValue base, CiValue index, Scale scale, int displacement) { |
97 super(kind); | 91 super(kind); |
92 this.base = base; | |
93 this.index = index; | |
94 this.scale = scale; | |
95 this.displacement = displacement; | |
98 | 96 |
99 this.base = base; | 97 assert !isConstant(base) && !isStackSlot(base); |
100 if (isConstant(index)) { | 98 assert !isConstant(index) && !isStackSlot(index); |
101 long longIndex = ((CiConstant) index).asLong(); | |
102 long longDisp = displacement + longIndex * scale.value; | |
103 if ((int) longIndex != longIndex || (int) longDisp != longDisp) { | |
104 throw new Error("integer overflow when computing constant displacement"); | |
105 } | |
106 this.displacement = (int) longDisp; | |
107 this.index = IllegalValue; | |
108 this.scale = Scale.Times1; | |
109 } else { | |
110 this.index = index; | |
111 this.scale = scale; | |
112 this.displacement = displacement; | |
113 } | |
114 } | 99 } |
115 | 100 |
116 /** | 101 /** |
117 * A scaling factor used in complex addressing modes such as those supported by x86 platforms. | 102 * A scaling factor used in complex addressing modes such as those supported by x86 platforms. |
118 */ | 103 */ |
120 Times1(1, 0), | 105 Times1(1, 0), |
121 Times2(2, 1), | 106 Times2(2, 1), |
122 Times4(4, 2), | 107 Times4(4, 2), |
123 Times8(8, 3); | 108 Times8(8, 3); |
124 | 109 |
125 Scale(int value, int log2) { | 110 private Scale(int value, int log2) { |
126 this.value = value; | 111 this.value = value; |
127 this.log2 = log2; | 112 this.log2 = log2; |
128 } | 113 } |
129 | 114 |
130 /** | 115 /** |
136 * The {@linkplain #value value} of this scale log 2. | 121 * The {@linkplain #value value} of this scale log 2. |
137 */ | 122 */ |
138 public final int log2; | 123 public final int log2; |
139 | 124 |
140 public static Scale fromInt(int scale) { | 125 public static Scale fromInt(int scale) { |
141 // Checkstyle: stop | |
142 switch (scale) { | 126 switch (scale) { |
143 case 1: return Times1; | 127 case 1: return Times1; |
144 case 2: return Times2; | 128 case 2: return Times2; |
145 case 4: return Times4; | 129 case 4: return Times4; |
146 case 8: return Times8; | 130 case 8: return Times8; |
147 default: throw new IllegalArgumentException(String.valueOf(scale)); | 131 default: throw new IllegalArgumentException(String.valueOf(scale)); |
148 } | |
149 // Checkstyle: resume | |
150 } | |
151 | |
152 public static Scale fromShift(int shift) { | |
153 return fromInt(1 << shift); | |
154 } | |
155 } | |
156 | |
157 /** | |
158 * Encodes the possible addressing modes as a simple value. | |
159 */ | |
160 public enum Format { | |
161 BASE, | |
162 BASE_DISP, | |
163 BASE_INDEX, | |
164 BASE_INDEX_DISP, | |
165 PLACEHOLDER; | |
166 } | |
167 | |
168 /** | |
169 * Returns the {@link Format encoded addressing mode} that this {@code CiAddress} represents. | |
170 * @return the encoded addressing mode | |
171 */ | |
172 public Format format() { | |
173 if (this == Placeholder) { | |
174 return Format.PLACEHOLDER; | |
175 } | |
176 assert isLegal(base); | |
177 if (isLegal(index)) { | |
178 if (displacement != 0) { | |
179 return Format.BASE_INDEX_DISP; | |
180 } else { | |
181 return Format.BASE_INDEX; | |
182 } | |
183 } else { | |
184 if (displacement != 0) { | |
185 return Format.BASE_DISP; | |
186 } else { | |
187 return Format.BASE; | |
188 } | 132 } |
189 } | 133 } |
190 } | 134 } |
191 | 135 |
192 private static String signed(int i) { | |
193 if (i >= 0) { | |
194 return "+" + i; | |
195 } | |
196 return String.valueOf(i); | |
197 } | |
198 | |
199 @Override | 136 @Override |
200 public String toString() { | 137 public String toString() { |
201 // Checkstyle: stop | 138 if (this == Placeholder) { |
202 switch (format()) { | 139 return "[<placeholder>]"; |
203 case BASE : return "[" + base + kindSuffix() + "]"; | |
204 case BASE_DISP : return "[" + base + signed(displacement) + kindSuffix() + "]"; | |
205 case BASE_INDEX : return "[" + base + "+" + index + kindSuffix() + "]"; | |
206 case BASE_INDEX_DISP : return "[" + base + "+(" + index + "*" + scale.value + ")" + signed(displacement) + kindSuffix() + "]"; | |
207 case PLACEHOLDER : return "[<placeholder>]"; | |
208 default : throw new IllegalArgumentException("unknown format: " + format()); | |
209 } | 140 } |
210 // Checkstyle: resume | 141 |
142 StringBuilder s = new StringBuilder(); | |
143 s.append(kind.javaName).append("["); | |
144 String sep = ""; | |
145 if (isLegal(base)) { | |
146 s.append(base); | |
147 sep = " + "; | |
148 } | |
149 if (isLegal(index)) { | |
150 s.append(sep).append(index).append(" * ").append(scale.value); | |
151 sep = " + "; | |
152 } | |
153 if (displacement < 0) { | |
154 s.append(" - ").append(-displacement); | |
155 } else if (displacement > 0) { | |
156 s.append(sep).append(displacement); | |
157 } | |
158 s.append("]"); | |
159 return s.toString(); | |
211 } | 160 } |
212 | 161 |
213 @Override | 162 @Override |
214 public boolean equals(Object obj) { | 163 public boolean equals(Object obj) { |
215 if (obj instanceof CiAddress) { | 164 if (obj instanceof CiAddress) { |
219 return false; | 168 return false; |
220 } | 169 } |
221 | 170 |
222 @Override | 171 @Override |
223 public int hashCode() { | 172 public int hashCode() { |
224 return (base.hashCode() << 4) | kind.ordinal(); | 173 return base.hashCode() ^ index.hashCode() ^ (displacement << 4) ^ (scale.value << 8) ^ (kind.ordinal() << 12); |
225 } | 174 } |
226 } | 175 } |