1 /*
2  * Copyright (c) 2016, 2018, 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 
24 
25 
26 package org.graalvm.compiler.core.aarch64;
27 
28 import org.graalvm.compiler.asm.aarch64.AArch64Address;
29 import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode;
30 import org.graalvm.compiler.core.common.LIRKind;
31 import org.graalvm.compiler.graph.NodeClass;
32 import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
33 import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
34 import org.graalvm.compiler.nodeinfo.NodeInfo;
35 import org.graalvm.compiler.nodes.NodeView;
36 import org.graalvm.compiler.nodes.ValueNode;
37 import org.graalvm.compiler.nodes.memory.address.AddressNode;
38 import org.graalvm.compiler.nodes.spi.LIRLowerable;
39 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
40 
41 import jdk.vm.ci.meta.AllocatableValue;
42 import jdk.vm.ci.meta.Value;
43 
44 /**
45  * Represents an AArch64 address in the graph.
46  */
47 @NodeInfo
48 public class AArch64AddressNode extends AddressNode implements LIRLowerable {
49 
50     public static final NodeClass<AArch64AddressNode> TYPE = NodeClass.create(AArch64AddressNode.class);
51 
52     @OptionalInput private ValueNode base;
53 
54     @OptionalInput private ValueNode index;
55     private AArch64Address.AddressingMode addressingMode;
56 
57     private long displacement;
58     private int scaleFactor;
59 
AArch64AddressNode(ValueNode base)60     public AArch64AddressNode(ValueNode base) {
61         this(base, null);
62     }
63 
AArch64AddressNode(ValueNode base, ValueNode index)64     public AArch64AddressNode(ValueNode base, ValueNode index) {
65         super(TYPE);
66         this.base = base;
67         this.index = index;
68         this.addressingMode = AddressingMode.REGISTER_OFFSET;
69         this.displacement = 0;
70         this.scaleFactor = 1;
71     }
72 
73     @Override
generate(NodeLIRBuilderTool gen)74     public void generate(NodeLIRBuilderTool gen) {
75         LIRGeneratorTool tool = gen.getLIRGeneratorTool();
76 
77         AllocatableValue baseValue = base == null ? Value.ILLEGAL : tool.asAllocatable(gen.operand(base));
78         AllocatableValue indexValue = index == null ? Value.ILLEGAL : tool.asAllocatable(gen.operand(index));
79 
80         AllocatableValue baseReference = LIRKind.derivedBaseFromValue(baseValue);
81         AllocatableValue indexReference;
82         if (index == null) {
83             indexReference = null;
84         } else if (addressingMode.equals(AddressingMode.IMMEDIATE_UNSCALED)) {
85             indexReference = LIRKind.derivedBaseFromValue(indexValue);
86         } else {
87             if (LIRKind.isValue(indexValue.getValueKind())) {
88                 indexReference = null;
89             } else {
90                 indexReference = Value.ILLEGAL;
91             }
92         }
93 
94         LIRKind kind = LIRKind.combineDerived(tool.getLIRKind(stamp(NodeView.DEFAULT)), baseReference, indexReference);
95         gen.setResult(this, new AArch64AddressValue(kind, baseValue, indexValue, (int) displacement, scaleFactor, addressingMode));
96     }
97 
98     @Override
getBase()99     public ValueNode getBase() {
100         return base;
101     }
102 
setBase(ValueNode base)103     public void setBase(ValueNode base) {
104         // allow modification before inserting into the graph
105         if (isAlive()) {
106             updateUsages(this.base, base);
107         }
108         this.base = base;
109     }
110 
111     @Override
getIndex()112     public ValueNode getIndex() {
113         return index;
114     }
115 
setIndex(ValueNode index)116     public void setIndex(ValueNode index) {
117         // allow modification before inserting into the graph
118         if (isAlive()) {
119             updateUsages(this.index, index);
120         }
121         this.index = index;
122     }
123 
getDisplacement()124     public long getDisplacement() {
125         return displacement;
126     }
127 
setDisplacement(long displacement, int scaleFactor, AArch64Address.AddressingMode addressingMode)128     public void setDisplacement(long displacement, int scaleFactor, AArch64Address.AddressingMode addressingMode) {
129         this.displacement = displacement;
130         this.scaleFactor = scaleFactor;
131         this.addressingMode = addressingMode;
132     }
133 
134     @Override
getMaxConstantDisplacement()135     public long getMaxConstantDisplacement() {
136         return displacement;
137     }
138 
getAddressingMode()139     public AddressingMode getAddressingMode() {
140         return addressingMode;
141     }
142 }
143