Mirror of the JODE repository
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
jode/jode/src/net/sf/jode/flow/InstructionBlock.java

161 lines
5.1 KiB

/* InstructionBlock Copyright (C) 1998-2002 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; see the file COPYING.LESSER. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package net.sf.jode.flow;
import net.sf.jode.type.Type;
import net.sf.jode.decompiler.TabbedPrintWriter;
import net.sf.jode.decompiler.LocalInfo;
import net.sf.jode.expr.Expression;
import net.sf.jode.expr.StoreInstruction;
import net.sf.jode.expr.LocalStoreOperator;
///#def COLLECTIONS java.util
import java.util.Set;
///#enddef
/**
* This is the structured block for atomic instructions.
*/
public class InstructionBlock extends InstructionContainer {
/**
* The loads that are on the stack before cond is executed.
*/
VariableStack stack;
/**
* The local to which we push to, if the instruction is non void
*/
LocalInfo pushedLocal = null;
/**
* Tells if this expression is a initializing declaration. This
* can only be set to true and then never be reset. It is changed
* by makeDeclaration. */
boolean isDeclaration = false;
public InstructionBlock(Expression instr) {
super(instr);
}
/**
* This does take the instr into account and modifies stack
* accordingly. It then calls super.mapStackToLocal.
* @param stack the stack before the instruction is called
* @return stack the stack afterwards.
*/
public VariableStack mapStackToLocal(VariableStack stack) {
VariableStack newStack;
int params = instr.getFreeOperandCount();
if (params > 0)
this.stack = stack.peek(params);
if (instr.getType() != Type.tVoid) {
pushedLocal = new LocalInfo();
pushedLocal.setType(instr.getType());
newStack = stack.poppush(params, pushedLocal);
} else if (params > 0) {
newStack = stack.pop(params);
} else
newStack = stack;
return super.mapStackToLocal(newStack);
}
public void removePush() {
if (stack != null)
instr = stack.mergeIntoExpression(instr);
if (pushedLocal != null) {
Expression store = new StoreInstruction
(new LocalStoreOperator
(pushedLocal.getType(), pushedLocal)).addOperand(instr);
instr = store;
}
super.removePush();
}
/**
* Tells if this block needs braces when used in a if or while block.
* @return true if this block should be sorrounded by braces.
*/
public boolean needsBraces() {
return isDeclaration || (declare != null && !declare.isEmpty());
}
/**
* Check if this is an local store instruction to a not yet declared
* variable. In that case mark this as declaration and return the
* variable.
*/
public void checkDeclaration(Set declareSet) {
if (instr instanceof StoreInstruction
&& (((StoreInstruction)instr).getLValue()
instanceof LocalStoreOperator)) {
StoreInstruction storeOp = (StoreInstruction) instr;
LocalInfo local =
((LocalStoreOperator) storeOp.getLValue()).getLocalInfo();
if (declareSet.contains(local)) {
/* Special case: This is a variable assignment, and
* the variable has not been declared before. We can
* change this to a initializing variable declaration.
*/
isDeclaration = true;
declareSet.remove(local);
}
}
}
/**
* Make the declarations, i.e. initialize the declare variable
* to correct values. This will declare every variable that
* is marked as used, but not done.
* @param done The set of the already declare variables.
*/
public void makeDeclaration(Set done) {
super.makeDeclaration(done);
checkDeclaration(declare);
}
public void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException
{
if (isDeclaration) {
StoreInstruction store = (StoreInstruction) instr;
LocalInfo local =
((LocalStoreOperator) store.getLValue()).getLocalInfo();
writer.startOp(TabbedPrintWriter.NO_PAREN, 0);
local.dumpDeclaration(writer);
writer.breakOp();
writer.print(" = ");
store.getSubExpressions()[1].makeInitializer(local.getType());
store.getSubExpressions()[1].dumpExpression(TabbedPrintWriter.IMPL_PAREN,
writer);
writer.endOp();
} else {
try {
if (instr.getType() != Type.tVoid) {
writer.print("PUSH ");
instr.dumpExpression(TabbedPrintWriter.IMPL_PAREN, writer);
} else
instr.dumpExpression(TabbedPrintWriter.NO_PAREN, writer);
} catch (RuntimeException ex) {
writer.print("(RUNTIME ERROR IN EXPRESSION)");
}
}
writer.println(";");
}
}