001/* 002 * Copyright (c) 2009, 2012, 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 com.oracle.graal.lir; 024 025import java.util.*; 026 027import com.oracle.graal.compiler.common.cfg.*; 028import com.oracle.graal.lir.StandardOp.BlockEndOp; 029import com.oracle.graal.lir.StandardOp.LabelOp; 030 031/** 032 * This class implements the overall container for the LIR graph and directs its construction, 033 * optimization, and finalization. 034 */ 035public class LIR { 036 037 private final AbstractControlFlowGraph<?> cfg; 038 039 /** 040 * The linear-scan ordered list of blocks. 041 */ 042 private final List<? extends AbstractBlockBase<?>> linearScanOrder; 043 044 /** 045 * The order in which the code is emitted. 046 */ 047 private final List<? extends AbstractBlockBase<?>> codeEmittingOrder; 048 049 private int firstVariableNumber; 050 051 private int numVariables; 052 053 private final BlockMap<List<LIRInstruction>> lirInstructions; 054 055 private boolean hasArgInCallerFrame; 056 057 /** 058 * Creates a new LIR instance for the specified compilation. 059 */ 060 public LIR(AbstractControlFlowGraph<?> cfg, List<? extends AbstractBlockBase<?>> linearScanOrder, List<? extends AbstractBlockBase<?>> codeEmittingOrder) { 061 this.cfg = cfg; 062 this.codeEmittingOrder = codeEmittingOrder; 063 this.linearScanOrder = linearScanOrder; 064 this.lirInstructions = new BlockMap<>(cfg); 065 } 066 067 public AbstractControlFlowGraph<?> getControlFlowGraph() { 068 return cfg; 069 } 070 071 /** 072 * Determines if any instruction in the LIR has debug info associated with it. 073 */ 074 public boolean hasDebugInfo() { 075 for (AbstractBlockBase<?> b : linearScanOrder()) { 076 for (LIRInstruction op : getLIRforBlock(b)) { 077 if (op.hasState()) { 078 return true; 079 } 080 } 081 } 082 return false; 083 } 084 085 public List<LIRInstruction> getLIRforBlock(AbstractBlockBase<?> block) { 086 return lirInstructions.get(block); 087 } 088 089 public void setLIRforBlock(AbstractBlockBase<?> block, List<LIRInstruction> list) { 090 assert getLIRforBlock(block) == null : "lir instruction list should only be initialized once"; 091 lirInstructions.put(block, list); 092 } 093 094 /** 095 * Gets the linear scan ordering of blocks as a list. 096 * 097 * @return the blocks in linear scan order 098 */ 099 public List<? extends AbstractBlockBase<?>> linearScanOrder() { 100 return linearScanOrder; 101 } 102 103 public List<? extends AbstractBlockBase<?>> codeEmittingOrder() { 104 return codeEmittingOrder; 105 } 106 107 public int numVariables() { 108 return numVariables; 109 } 110 111 public int nextVariable() { 112 return firstVariableNumber + numVariables++; 113 } 114 115 public void setFirstVariableNumber(int num) { 116 firstVariableNumber = num; 117 } 118 119 public void setHasArgInCallerFrame() { 120 hasArgInCallerFrame = true; 121 } 122 123 /** 124 * Determines if any of the parameters to the method are passed via the stack where the 125 * parameters are located in the caller's frame. 126 */ 127 public boolean hasArgInCallerFrame() { 128 return hasArgInCallerFrame; 129 } 130 131 /** 132 * Gets the exception edge (if any) originating at a given operation. 133 */ 134 public static LabelRef getExceptionEdge(LIRInstruction op) { 135 final LabelRef[] exceptionEdge = {null}; 136 op.forEachState(state -> { 137 if (state.exceptionEdge != null) { 138 assert exceptionEdge[0] == null; 139 exceptionEdge[0] = state.exceptionEdge; 140 } 141 }); 142 return exceptionEdge[0]; 143 } 144 145 /** 146 * The maximum distance an operation with an {@linkplain #getExceptionEdge(LIRInstruction) 147 * exception edge} can be from the last instruction of a LIR block. The value of 3 is based on a 148 * non-void call operation that has an exception edge. Such a call may move the result to 149 * another register and then spill it. 150 * <p> 151 * The rationale for such a constant is to limit the search for an insertion point when adding 152 * move operations at the end of a block. Such moves must be inserted before all control flow 153 * instructions. 154 */ 155 public static final int MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END = 3; 156 157 public static boolean verifyBlock(LIR lir, AbstractBlockBase<?> block) { 158 List<LIRInstruction> ops = lir.getLIRforBlock(block); 159 if (ops.size() == 0) { 160 return false; 161 } 162 LIRInstruction opWithExceptionEdge = null; 163 int index = 0; 164 int lastIndex = ops.size() - 1; 165 for (LIRInstruction op : ops.subList(0, lastIndex)) { 166 assert !(op instanceof BlockEndOp) : op.getClass(); 167 LabelRef exceptionEdge = getExceptionEdge(op); 168 if (exceptionEdge != null) { 169 assert opWithExceptionEdge == null : "multiple ops with an exception edge not allowed"; 170 opWithExceptionEdge = op; 171 int distanceFromEnd = lastIndex - index; 172 assert distanceFromEnd <= MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END; 173 } 174 index++; 175 } 176 LIRInstruction end = ops.get(lastIndex); 177 assert end instanceof BlockEndOp : end.getClass(); 178 return true; 179 } 180 181 public static boolean verifyBlocks(LIR lir, List<? extends AbstractBlockBase<?>> blocks) { 182 for (AbstractBlockBase<?> block : blocks) { 183 for (AbstractBlockBase<?> sux : block.getSuccessors()) { 184 assert blocks.contains(sux) : "missing successor from: " + block + "to: " + sux; 185 } 186 for (AbstractBlockBase<?> pred : block.getPredecessors()) { 187 assert blocks.contains(pred) : "missing predecessor from: " + block + "to: " + pred; 188 } 189 if (!verifyBlock(lir, block)) { 190 return false; 191 } 192 } 193 return true; 194 } 195 196 public void resetLabels() { 197 198 for (AbstractBlockBase<?> block : codeEmittingOrder()) { 199 for (LIRInstruction inst : lirInstructions.get(block)) { 200 if (inst instanceof LabelOp) { 201 ((LabelOp) inst).getLabel().reset(); 202 } 203 } 204 } 205 } 206 207}