1 /*
2  * Copyright (c) 2009, 2012, 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 package org.graalvm.compiler.lir;
26 
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.List;
30 
31 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
32 import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph;
33 import org.graalvm.compiler.core.common.cfg.BlockMap;
34 import org.graalvm.compiler.debug.DebugContext;
35 import org.graalvm.compiler.lir.StandardOp.BlockEndOp;
36 import org.graalvm.compiler.lir.StandardOp.LabelOp;
37 import org.graalvm.compiler.lir.gen.LIRGenerator;
38 import org.graalvm.compiler.options.OptionValues;
39 
40 /**
41  * This class implements the overall container for the LIR graph and directs its construction,
42  * optimization, and finalization.
43  */
44 public final class LIR extends LIRGenerator.VariableProvider {
45 
46     private final AbstractControlFlowGraph<?> cfg;
47 
48     /**
49      * The linear-scan ordered list of blocks.
50      */
51     private final AbstractBlockBase<?>[] linearScanOrder;
52 
53     /**
54      * The order in which the code is emitted.
55      */
56     private final AbstractBlockBase<?>[] codeEmittingOrder;
57 
58     /**
59      * Map from {@linkplain AbstractBlockBase block} to {@linkplain LIRInstruction}s. Note that we
60      * are using {@link ArrayList} instead of {@link List} to avoid interface dispatch.
61      */
62     private final BlockMap<ArrayList<LIRInstruction>> lirInstructions;
63 
64     private boolean hasArgInCallerFrame;
65 
66     private final OptionValues options;
67 
68     private final DebugContext debug;
69 
70     /**
71      * Creates a new LIR instance for the specified compilation.
72      */
LIR(AbstractControlFlowGraph<?> cfg, AbstractBlockBase<?>[] linearScanOrder, AbstractBlockBase<?>[] codeEmittingOrder, OptionValues options, DebugContext debug)73     public LIR(AbstractControlFlowGraph<?> cfg, AbstractBlockBase<?>[] linearScanOrder, AbstractBlockBase<?>[] codeEmittingOrder, OptionValues options, DebugContext debug) {
74         this.cfg = cfg;
75         this.codeEmittingOrder = codeEmittingOrder;
76         this.linearScanOrder = linearScanOrder;
77         this.lirInstructions = new BlockMap<>(cfg);
78         this.options = options;
79         this.debug = debug;
80     }
81 
getControlFlowGraph()82     public AbstractControlFlowGraph<?> getControlFlowGraph() {
83         return cfg;
84     }
85 
getOptions()86     public OptionValues getOptions() {
87         return options;
88     }
89 
getDebug()90     public DebugContext getDebug() {
91         return debug;
92     }
93 
94     /**
95      * Determines if any instruction in the LIR has debug info associated with it.
96      */
hasDebugInfo()97     public boolean hasDebugInfo() {
98         for (AbstractBlockBase<?> b : linearScanOrder()) {
99             for (LIRInstruction op : getLIRforBlock(b)) {
100                 if (op.hasState()) {
101                     return true;
102                 }
103             }
104         }
105         return false;
106     }
107 
getLIRforBlock(AbstractBlockBase<?> block)108     public ArrayList<LIRInstruction> getLIRforBlock(AbstractBlockBase<?> block) {
109         return lirInstructions.get(block);
110     }
111 
setLIRforBlock(AbstractBlockBase<?> block, ArrayList<LIRInstruction> list)112     public void setLIRforBlock(AbstractBlockBase<?> block, ArrayList<LIRInstruction> list) {
113         assert getLIRforBlock(block) == null : "lir instruction list should only be initialized once";
114         lirInstructions.put(block, list);
115     }
116 
117     /**
118      * Gets the linear scan ordering of blocks as an array.
119      *
120      * @return the blocks in linear scan order
121      */
linearScanOrder()122     public AbstractBlockBase<?>[] linearScanOrder() {
123         return linearScanOrder;
124     }
125 
codeEmittingOrder()126     public AbstractBlockBase<?>[] codeEmittingOrder() {
127         return codeEmittingOrder;
128     }
129 
setHasArgInCallerFrame()130     public void setHasArgInCallerFrame() {
131         hasArgInCallerFrame = true;
132     }
133 
134     /**
135      * Determines if any of the parameters to the method are passed via the stack where the
136      * parameters are located in the caller's frame.
137      */
hasArgInCallerFrame()138     public boolean hasArgInCallerFrame() {
139         return hasArgInCallerFrame;
140     }
141 
142     /**
143      * Gets the next non-{@code null} block in a list.
144      *
145      * @param blocks list of blocks
146      * @param blockIndex index of the current block
147      * @return the next block in the list that is none {@code null} or {@code null} if there is no
148      *         such block
149      */
getNextBlock(AbstractBlockBase<?>[] blocks, int blockIndex)150     public static AbstractBlockBase<?> getNextBlock(AbstractBlockBase<?>[] blocks, int blockIndex) {
151         for (int nextIndex = blockIndex + 1; nextIndex > 0 && nextIndex < blocks.length; nextIndex++) {
152             AbstractBlockBase<?> nextBlock = blocks[nextIndex];
153             if (nextBlock != null) {
154                 return nextBlock;
155             }
156         }
157         return null;
158     }
159 
160     /**
161      * Gets the exception edge (if any) originating at a given operation.
162      */
getExceptionEdge(LIRInstruction op)163     public static LabelRef getExceptionEdge(LIRInstruction op) {
164         final LabelRef[] exceptionEdge = {null};
165         op.forEachState(state -> {
166             if (state.exceptionEdge != null) {
167                 assert exceptionEdge[0] == null;
168                 exceptionEdge[0] = state.exceptionEdge;
169             }
170         });
171         return exceptionEdge[0];
172     }
173 
174     /**
175      * The maximum distance an operation with an {@linkplain #getExceptionEdge(LIRInstruction)
176      * exception edge} can be from the last instruction of a LIR block. The value of 3 is based on a
177      * non-void call operation that has an exception edge. Such a call may move the result to
178      * another register and then spill it.
179      * <p>
180      * The rationale for such a constant is to limit the search for an insertion point when adding
181      * move operations at the end of a block. Such moves must be inserted before all control flow
182      * instructions.
183      */
184     public static final int MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END = 3;
185 
verifyBlock(LIR lir, AbstractBlockBase<?> block)186     public static boolean verifyBlock(LIR lir, AbstractBlockBase<?> block) {
187         ArrayList<LIRInstruction> ops = lir.getLIRforBlock(block);
188         if (ops.size() == 0) {
189             return false;
190         }
191         assert ops.get(0) instanceof LabelOp : String.format("Not a Label %s (Block %s)", ops.get(0).getClass(), block);
192         LIRInstruction opWithExceptionEdge = null;
193         int index = 0;
194         int lastIndex = ops.size() - 1;
195         for (LIRInstruction op : ops.subList(0, lastIndex)) {
196             assert !(op instanceof BlockEndOp) : String.format("BlockEndOp %s (Block %s)", op.getClass(), block);
197             LabelRef exceptionEdge = getExceptionEdge(op);
198             if (exceptionEdge != null) {
199                 assert opWithExceptionEdge == null : "multiple ops with an exception edge not allowed";
200                 opWithExceptionEdge = op;
201                 int distanceFromEnd = lastIndex - index;
202                 assert distanceFromEnd <= MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END;
203             }
204             index++;
205         }
206         LIRInstruction end = ops.get(lastIndex);
207         assert end instanceof BlockEndOp : String.format("Not a BlockEndOp %s (Block %s)", end.getClass(), block);
208         return true;
209     }
210 
verifyBlocks(LIR lir, AbstractBlockBase<?>[] blocks)211     public static boolean verifyBlocks(LIR lir, AbstractBlockBase<?>[] blocks) {
212         for (AbstractBlockBase<?> block : blocks) {
213             if (block == null) {
214                 continue;
215             }
216             for (AbstractBlockBase<?> sux : block.getSuccessors()) {
217                 assert Arrays.asList(blocks).contains(sux) : "missing successor from: " + block + "to: " + sux;
218             }
219             for (AbstractBlockBase<?> pred : block.getPredecessors()) {
220                 assert Arrays.asList(blocks).contains(pred) : "missing predecessor from: " + block + "to: " + pred;
221             }
222             if (!verifyBlock(lir, block)) {
223                 return false;
224             }
225         }
226         return true;
227     }
228 
resetLabels()229     public void resetLabels() {
230 
231         for (AbstractBlockBase<?> block : codeEmittingOrder()) {
232             if (block == null) {
233                 continue;
234             }
235             for (LIRInstruction inst : lirInstructions.get(block)) {
236                 if (inst instanceof LabelOp) {
237                     ((LabelOp) inst).getLabel().reset();
238                 }
239             }
240         }
241     }
242 
243 }
244