1 /*
   2  * Copyright (c) 2009, 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 
  24 
  25 package org.graalvm.compiler.core.gen;
  26 
  27 import static org.graalvm.compiler.core.gen.InstructionPrinter.InstructionLineColumn.BCI;
  28 import static org.graalvm.compiler.core.gen.InstructionPrinter.InstructionLineColumn.END;
  29 import static org.graalvm.compiler.core.gen.InstructionPrinter.InstructionLineColumn.INSTRUCTION;
  30 import static org.graalvm.compiler.core.gen.InstructionPrinter.InstructionLineColumn.USE;
  31 import static org.graalvm.compiler.core.gen.InstructionPrinter.InstructionLineColumn.VALUE;
  32 
  33 import org.graalvm.compiler.debug.LogStream;
  34 import org.graalvm.compiler.nodes.StateSplit;
  35 import org.graalvm.compiler.nodes.ValueNode;
  36 import org.graalvm.compiler.nodes.ValueNodeUtil;
  37 
  38 /**
  39  * A utility for {@linkplain #printInstruction(ValueNode) printing} a node as an expression or
  40  * statement.
  41  */
  42 public class InstructionPrinter {
  43 
  44     /**
  45      * The columns printed in a tabulated instruction
  46      * {@linkplain InstructionPrinter#printInstructionListing(ValueNode) listing}.
  47      */
  48     public enum InstructionLineColumn {
  49         /**
  50          * The instruction's bytecode index.
  51          */
  52         BCI(2, "bci"),
  53 
  54         /**
  55          * The instruction's use count.
  56          */
  57         USE(7, "use"),
  58 
  59         /**
  60          * The instruction as a value.
  61          */
  62         VALUE(12, "tid"),
  63 
  64         /**
  65          * The instruction formatted as an expression or statement.
  66          */
  67         INSTRUCTION(19, "instr"),
  68 
  69         END(60, "");
  70 
  71         final int position;
  72         final String label;
  73 
  74         InstructionLineColumn(int position, String label) {
  75             this.position = position;
  76             this.label = label;
  77         }
  78 
  79         /**
  80          * Prints this column's label to a given stream after padding the stream with '_' characters
  81          * until its {@linkplain LogStream#position() position} is equal to this column's position.
  82          *
  83          * @param out the print stream
  84          */
  85         public void printLabel(LogStream out) {
  86             out.fillTo(position + out.indentationLevel(), '_');
  87             out.print(label);
  88         }
  89 
  90         /**
  91          * Prints space characters to a given stream until its {@linkplain LogStream#position()
  92          * position} is equal to this column's position.
  93          *
  94          * @param out the print stream
  95          */
  96         public void advance(LogStream out) {
  97             out.fillTo(position + out.indentationLevel(), ' ');
  98         }
  99     }
 100 
 101     private final LogStream out;
 102 
 103     public InstructionPrinter(LogStream out) {
 104         this.out = out;
 105     }
 106 
 107     public LogStream out() {
 108         return out;
 109     }
 110 
 111     /**
 112      * Prints a header for the tabulated data printed by {@link #printInstructionListing(ValueNode)}
 113      * .
 114      */
 115     public void printInstructionListingHeader() {
 116         BCI.printLabel(out);
 117         USE.printLabel(out);
 118         VALUE.printLabel(out);
 119         INSTRUCTION.printLabel(out);
 120         END.printLabel(out);
 121         out.println();
 122     }
 123 
 124     /**
 125      * Prints an instruction listing on one line. The instruction listing is composed of the columns
 126      * specified by {@link InstructionLineColumn}.
 127      *
 128      * @param instruction the instruction to print
 129      */
 130     public void printInstructionListing(ValueNode instruction) {
 131         int indentation = out.indentationLevel();
 132         out.fillTo(BCI.position + indentation, ' ').print(0).fillTo(USE.position + indentation, ' ').print("0").fillTo(VALUE.position + indentation, ' ').print(
 133                         ValueNodeUtil.valueString(instruction)).fillTo(
 134                                         INSTRUCTION.position + indentation, ' ');
 135         printInstruction(instruction);
 136         if (instruction instanceof StateSplit) {
 137             out.print("  [state: " + ((StateSplit) instruction).stateAfter() + "]");
 138         }
 139         out.println();
 140     }
 141 
 142     public void printInstruction(ValueNode node) {
 143         out.print(node.toString());
 144     }
 145 }