diff options
Diffstat (limited to 'dx/src/com/android/dx/command/dump/SsaDumper.java')
-rw-r--r-- | dx/src/com/android/dx/command/dump/SsaDumper.java | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/dx/src/com/android/dx/command/dump/SsaDumper.java b/dx/src/com/android/dx/command/dump/SsaDumper.java new file mode 100644 index 0000000..de44c83 --- /dev/null +++ b/dx/src/com/android/dx/command/dump/SsaDumper.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.dx.command.dump; + +import com.android.dx.cf.code.ConcreteMethod; +import com.android.dx.cf.code.Ropper; +import com.android.dx.cf.iface.Member; +import com.android.dx.cf.iface.Method; +import com.android.dx.rop.code.RopMethod; +import com.android.dx.rop.code.TranslationAdvice; +import com.android.dx.rop.code.DexTranslationAdvice; +import com.android.dx.rop.code.AccessFlags; +import com.android.dx.ssa.DeadCodeRemover; +import com.android.dx.ssa.PhiTypeResolver; +import com.android.dx.ssa.SsaBasicBlock; +import com.android.dx.ssa.SsaConverter; +import com.android.dx.ssa.SsaInsn; +import com.android.dx.ssa.SsaMethod; +import com.android.dx.ssa.Optimizer; +import com.android.dx.ssa.ConstCollector; +import com.android.dx.ssa.SCCP; +import com.android.dx.ssa.LiteralOpUpgrader; +import com.android.dx.ssa.back.SsaToRop; +import com.android.dx.util.ByteArray; +import com.android.dx.util.Hex; +import com.android.dx.util.IntList; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Collections; +import java.util.EnumSet; + +/** + * Dumper for the SSA-translated blocks of a method. + */ +public class SsaDumper extends BlockDumper { + /** + * Does the dump. + * + * @param bytes {@code non-null;} bytes of the original class file + * @param out {@code non-null;} where to dump to + * @param filePath the file path for the class, excluding any base + * directory specification + * @param args commandline parsedArgs + */ + public static void dump(byte[] bytes, PrintStream out, + String filePath, Args args) { + SsaDumper sd = new SsaDumper(bytes, out, filePath, args); + sd.dump(); + } + + /** + * Constructs an instance. + * + * @param bytes {@code non-null;} bytes of the original class file + * @param out {@code non-null;} where to dump to + * @param filePath the file path for the class, excluding any base + * directory specification + * @param args commandline parsedArgs + */ + private SsaDumper(byte[] bytes, PrintStream out, String filePath, + Args args) { + super(bytes, out, filePath, true, args); + } + + /** {@inheritDoc} */ + @Override + public void endParsingMember(ByteArray bytes, int offset, String name, + String descriptor, Member member) { + if (!(member instanceof Method)) { + return; + } + + if (!shouldDumpMethod(name)) { + return; + } + + ConcreteMethod meth = + new ConcreteMethod((Method) member, classFile, true, true); + TranslationAdvice advice = DexTranslationAdvice.THE_ONE; + RopMethod rmeth = Ropper.convert(meth, advice); + SsaMethod ssaMeth = null; + boolean isStatic = AccessFlags.isStatic(meth.getAccessFlags()); + int paramWidth = computeParamWidth(meth, isStatic); + + if (args.ssaStep == null) { + ssaMeth = Optimizer.debugNoRegisterAllocation(rmeth, + paramWidth, isStatic, true, advice, + EnumSet.allOf(Optimizer.OptionalStep.class)); + } else if ("edge-split".equals(args.ssaStep)) { + ssaMeth = Optimizer.debugEdgeSplit(rmeth, paramWidth, + isStatic, true, advice); + } else if ("phi-placement".equals(args.ssaStep)) { + ssaMeth = Optimizer.debugPhiPlacement( + rmeth, paramWidth, isStatic, true, advice); + } else if ("renaming".equals(args.ssaStep)) { + ssaMeth = Optimizer.debugRenaming( + rmeth, paramWidth, isStatic, true, advice); + } else if ("dead-code".equals(args.ssaStep)) { + ssaMeth = Optimizer.debugDeadCodeRemover( + rmeth, paramWidth, isStatic,true, advice); + } + + StringBuffer sb = new StringBuffer(2000); + + sb.append("first "); + sb.append(Hex.u2( + ssaMeth.blockIndexToRopLabel(ssaMeth.getEntryBlockIndex()))); + sb.append('\n'); + + ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks(); + ArrayList<SsaBasicBlock> sortedBlocks = + (ArrayList<SsaBasicBlock>) blocks.clone(); + Collections.sort(sortedBlocks, SsaBasicBlock.LABEL_COMPARATOR); + + for (SsaBasicBlock block : sortedBlocks) { + sb.append("block ") + .append(Hex.u2(block.getRopLabel())).append('\n'); + + BitSet preds = block.getPredecessors(); + + for (int i = preds.nextSetBit(0); i >= 0; + i = preds.nextSetBit(i+1)) { + sb.append(" pred "); + sb.append(Hex.u2(ssaMeth.blockIndexToRopLabel(i))); + sb.append('\n'); + } + + sb.append(" live in:" + block.getLiveInRegs()); + sb.append("\n"); + + for (SsaInsn insn : block.getInsns()) { + sb.append(" "); + sb.append(insn.toHuman()); + sb.append('\n'); + } + + if (block.getSuccessors().cardinality() == 0) { + sb.append(" returns\n"); + } else { + int primary = block.getPrimarySuccessorRopLabel(); + + IntList succLabelList = block.getRopLabelSuccessorList(); + + int szSuccLabels = succLabelList.size(); + + for (int i = 0; i < szSuccLabels; i++) { + sb.append(" next "); + sb.append(Hex.u2(succLabelList.get(i))); + + if (szSuccLabels != 1 && primary == succLabelList.get(i)) { + sb.append(" *"); + } + sb.append('\n'); + } + } + + sb.append(" live out:" + block.getLiveOutRegs()); + sb.append("\n"); + } + + suppressDump = false; + setAt(bytes, 0); + parsed(bytes, 0, bytes.size(), sb.toString()); + suppressDump = true; + } +} |