irgenerator.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 1,392 行 · 第 1/3 页

JAVA
1,392
字号
/*
 * $Id: IRGenerator.java,v 1.18 2004/02/24 08:05:06 epr Exp $
 *
 * mailto:madhu@madhu.com
 */
package org.jnode.vm.compiler.ir;

import java.util.Iterator;

import org.jnode.util.BootableArrayList;
import org.jnode.vm.bytecode.BytecodeParser;
import org.jnode.vm.bytecode.BytecodeVisitor;
import org.jnode.vm.classmgr.VmByteCode;
import org.jnode.vm.classmgr.VmConstClass;
import org.jnode.vm.classmgr.VmConstFieldRef;
import org.jnode.vm.classmgr.VmConstIMethodRef;
import org.jnode.vm.classmgr.VmConstMethodRef;
import org.jnode.vm.classmgr.VmConstString;
import org.jnode.vm.classmgr.VmMethod;
import org.jnode.vm.compiler.ir.quad.BinaryQuad;
import org.jnode.vm.compiler.ir.quad.ConditionalBranchQuad;
import org.jnode.vm.compiler.ir.quad.ConstantRefAssignQuad;
import org.jnode.vm.compiler.ir.quad.Quad;
import org.jnode.vm.compiler.ir.quad.UnaryQuad;
import org.jnode.vm.compiler.ir.quad.UnconditionalBranchQuad;
import org.jnode.vm.compiler.ir.quad.VarReturnQuad;
import org.jnode.vm.compiler.ir.quad.VariableRefAssignQuad;
import org.jnode.vm.compiler.ir.quad.VoidReturnQuad;

/**
 * Intermediate Representation Generator.
 * Visits bytecodes of a given method and translates them into a
 * list of Quads.
 */
public class IRGenerator extends BytecodeVisitor {
	private final static Constant NULL_CONSTANT = Constant.getInstance(null);
	private int nArgs;
	private int nLocals;
	private int maxStack;
	private int stackOffset;
	private Variable[] variables;
	private int address;
	private BootableArrayList quadList;
	private Iterator basicBlockIterator;
	private IRBasicBlock currentBlock;

	/**
	 * 
	 */
	public IRGenerator(IRControlFlowGraph cfg) {
		basicBlockIterator = cfg.basicBlockIterator();
		currentBlock = (IRBasicBlock) basicBlockIterator.next();
	}

	public BootableArrayList getQuadList() {
		return quadList;
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#setParser(org.jnode.vm.bytecode.BytecodeParser)
	 */
	public void setParser(BytecodeParser parser) {
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#startMethod(org.jnode.vm.classmgr.VmMethod)
	 */
	public void startMethod(VmMethod method) {
		VmByteCode code = method.getBytecode();
		nArgs = method.getArgSlotCount();
		nLocals = code.getNoLocals();
		maxStack = code.getMaxStack();
		stackOffset = nLocals;
		variables = new Variable[nLocals + maxStack];
		int index = 0;
		for (int i=0; i<nArgs; i+=1) {
			variables[index] = new MethodArgument(Operand.UNKNOWN, index);
			index += 1;
		}
		for (int i=nArgs; i<nLocals; i+=1) {
			variables[index] = new LocalVariable(Operand.UNKNOWN, index);
			index += 1;
		}
		for (int i=0; i<maxStack; i+=1) {
			variables[index] = new StackVariable(Operand.UNKNOWN, index);
			index += 1;
		}
		quadList = new BootableArrayList(code.getLength() >> 1);
		currentBlock.setVariables(variables);
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#endMethod()
	 */
	public void endMethod() {
		// patch last block
		currentBlock.resolvePhiReferences();
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#startInstruction(int)
	 */
	public void startInstruction(int address) {
		this.address = address;
		if (address >= currentBlock.getEndPC()) {
			currentBlock.resolvePhiReferences();
			currentBlock = (IRBasicBlock) basicBlockIterator.next();
			Iterator pi = currentBlock.getPredecessors().iterator();
			if (!pi.hasNext()) {
				// this must be the first block in the method
				return;
			}
			while (pi.hasNext()) {
				IRBasicBlock irb = (IRBasicBlock) pi.next();
				if (irb.getEndPC() <= address) {
					Variable[] prevVars = irb.getVariables();
					int n = prevVars.length;
					variables = new Variable[n];
					for (int i=0; i<n; i+=1) {
						variables[i] = prevVars[i];
					}
					currentBlock.setVariables(variables);
					return;
				}
			}
			throw new AssertionError("can't find a preceding basic block");
		}
		if (address < currentBlock.getStartPC() || address >= currentBlock.getEndPC()) {
			throw new AssertionError("instruction not in basic block!");
		}
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#endInstruction()
	 */
	public void endInstruction() {
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_nop()
	 */
	public void visit_nop() {
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_aconst_null()
	 */
	public void visit_aconst_null() {
		quadList.add(new ConstantRefAssignQuad(address, currentBlock, stackOffset,
			NULL_CONSTANT));
		stackOffset += 1;
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_iconst(int)
	 */
	public void visit_iconst(int value) {
		Quad quad = new ConstantRefAssignQuad(address, currentBlock, stackOffset,
					Constant.getInstance(value));
		quadList.add(quad);
		stackOffset += 1;
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lconst(long)
	 */
	public void visit_lconst(long value) {
		quadList.add(new ConstantRefAssignQuad(address, currentBlock, stackOffset,
			Constant.getInstance(value)));
		stackOffset += 2;
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_fconst(float)
	 */
	public void visit_fconst(float value) {
		quadList.add(new ConstantRefAssignQuad(address, currentBlock, stackOffset,
			Constant.getInstance(value)));
		stackOffset += 1;
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_dconst(double)
	 */
	public void visit_dconst(double value) {
		quadList.add(new ConstantRefAssignQuad(address, currentBlock, stackOffset,
			Constant.getInstance(value)));
		stackOffset += 2;
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_ldc(VmConstString)
	 */
	public void visit_ldc(VmConstString value) {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_iload(int)
	 */
	public void visit_iload(int index) {
		variables[index].setType(Operand.INT);
		variables[stackOffset].setType(Operand.INT);
		VariableRefAssignQuad assignQuad = new VariableRefAssignQuad(address, currentBlock,
			stackOffset, index);
		quadList.add(assignQuad);
		stackOffset += 1;
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lload(int)
	 */
	public void visit_lload(int index) {
		variables[index].setType(Operand.LONG);
		variables[stackOffset].setType(Operand.LONG);
		quadList.add(new VariableRefAssignQuad(address, currentBlock,
			stackOffset, index));
		stackOffset += 2;
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_fload(int)
	 */
	public void visit_fload(int index) {
		variables[index].setType(Operand.FLOAT);
		variables[stackOffset].setType(Operand.FLOAT);
		quadList.add(new VariableRefAssignQuad(address, currentBlock,
			stackOffset, index));
		stackOffset += 1;
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_dload(int)
	 */
	public void visit_dload(int index) {
		variables[index].setType(Operand.DOUBLE);
		variables[stackOffset].setType(Operand.DOUBLE);
		quadList.add(new VariableRefAssignQuad(address, currentBlock,
			stackOffset, index));
		stackOffset += 2;
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_aload(int)
	 */
	public void visit_aload(int index) {
		variables[index].setType(Operand.REFERENCE);
		variables[stackOffset].setType(Operand.REFERENCE);
		quadList.add(new VariableRefAssignQuad(address, currentBlock, stackOffset, index));
		stackOffset += 1;
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_iaload()
	 */
	public void visit_iaload() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_laload()
	 */
	public void visit_laload() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_faload()
	 */
	public void visit_faload() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_daload()
	 */
	public void visit_daload() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_aaload()
	 */
	public void visit_aaload() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_baload()
	 */
	public void visit_baload() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_caload()
	 */
	public void visit_caload() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_saload()
	 */
	public void visit_saload() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_istore(int)
	 */
	public void visit_istore(int index) {
		stackOffset -= 1;
		variables[index].setType(Operand.INT);
		variables[stackOffset].setType(Operand.INT);
		VariableRefAssignQuad assignQuad = new VariableRefAssignQuad(address, currentBlock, index, stackOffset);
		quadList.add(assignQuad);
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lstore(int)
	 */
	public void visit_lstore(int index) {
		stackOffset -= 2;
		variables[index].setType(Operand.LONG);
		variables[stackOffset].setType(Operand.LONG);
		quadList.add(new VariableRefAssignQuad(address, currentBlock, index, stackOffset));
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_fstore(int)
	 */
	public void visit_fstore(int index) {
		stackOffset -= 1;
		variables[index].setType(Operand.FLOAT);
		variables[stackOffset].setType(Operand.FLOAT);
		quadList.add(new VariableRefAssignQuad(address, currentBlock, index, stackOffset));
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_dstore(int)
	 */
	public void visit_dstore(int index) {
		stackOffset -= 2;
		variables[index].setType(Operand.DOUBLE);
		variables[stackOffset].setType(Operand.DOUBLE);
		quadList.add(new VariableRefAssignQuad(address, currentBlock, index, stackOffset));
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_astore(int)
	 */
	public void visit_astore(int index) {
		stackOffset -= 1;
		variables[index].setType(Operand.REFERENCE);
		variables[stackOffset].setType(Operand.REFERENCE);
		quadList.add(new VariableRefAssignQuad(address, currentBlock, index, stackOffset));
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_iastore()
	 */
	public void visit_iastore() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_lastore()
	 */
	public void visit_lastore() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_fastore()
	 */
	public void visit_fastore() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_dastore()
	 */
	public void visit_dastore() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_aastore()
	 */
	public void visit_aastore() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_bastore()
	 */
	public void visit_bastore() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_castore()
	 */
	public void visit_castore() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_sastore()
	 */
	public void visit_sastore() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_pop()
	 */
	public void visit_pop() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_pop2()
	 */
	public void visit_pop2() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_dup()
	 */
	public void visit_dup() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_dup_x1()
	 */
	public void visit_dup_x1() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_dup_x2()
	 */
	public void visit_dup_x2() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_dup2()
	 */
	public void visit_dup2() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

	/**
	 * @see org.jnode.vm.bytecode.BytecodeVisitor#visit_dup2_x1()
	 */
	public void visit_dup2_x1() {
		throw new IllegalArgumentException("byte code not yet supported");
	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?