declarables reworked

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@855 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 25 years ago
parent 863bb28203
commit a84ba609b9
  1. 11
      jode/jode/flow/CatchBlock.java
  2. 20
      jode/jode/flow/FlowBlock.java
  3. 7
      jode/jode/flow/IfThenElseBlock.java
  4. 25
      jode/jode/flow/InstructionBlock.java
  5. 7
      jode/jode/flow/InstructionContainer.java
  6. 21
      jode/jode/flow/LoopBlock.java
  7. 7
      jode/jode/flow/RetBlock.java
  8. 22
      jode/jode/flow/SequentialBlock.java
  9. 175
      jode/jode/flow/StructuredBlock.java
  10. 19
      jode/jode/flow/SynchronizedBlock.java

@ -24,6 +24,7 @@ import jode.expr.Expression;
import jode.expr.LocalLoadOperator;
import jode.expr.LocalStoreOperator;
import jode.expr.StoreInstruction;
import jode.util.SimpleSet;
/**
*
@ -120,10 +121,10 @@ public class CatchBlock extends StructuredBlock {
super.removePush();
}
public VariableSet getUsed() {
used = new VariableSet();
public SimpleSet getDeclarables() {
SimpleSet used = new SimpleSet();
if (exceptionLocal != null)
used.addElement(exceptionLocal);
used.add(exceptionLocal);
return used;
}
@ -133,7 +134,7 @@ public class CatchBlock extends StructuredBlock {
* is marked as used, but not done.
* @param done The set of the already declare variables.
*/
public void makeDeclaration(VariableSet done) {
public void makeDeclaration(SimpleSet done) {
super.makeDeclaration(done);
/* Normally we have to declare our exceptionLocal. This
* is automatically done in dumpSource.
@ -142,7 +143,7 @@ public class CatchBlock extends StructuredBlock {
* this block. In that case we do a transformation.
*/
if (declare.contains(exceptionLocal))
declare.removeElement(exceptionLocal);
declare.remove(exceptionLocal);
else {
LocalInfo dummyLocal = new LocalInfo();
Expression store = new StoreInstruction

@ -27,6 +27,7 @@ import jode.decompiler.LocalInfo;
import jode.expr.Expression;
import jode.expr.CombineableOperator;
import jode.util.SimpleDictionary;
import jode.util.SimpleSet;
/**
* A flow block is the structure of which the flow graph consists. A
@ -1489,14 +1490,19 @@ public class FlowBlock {
nextByAddr.removeOnetimeLocals();
}
public void makeDeclaration(VariableSet param) {
in.merge(param);
in.subtract(param);
public void mergeParams(LocalInfo[] param) {
VariableSet paramSet = new VariableSet(param);
in.merge(paramSet);
in.subtract(paramSet);
}
public void makeDeclaration(LocalInfo[] param) {
block.propagateUsage();
Enumeration enum = param.elements();
while (enum.hasMoreElements())
((LocalInfo) enum.nextElement()).guessName();
block.makeDeclaration(param);
SimpleSet declared = new SimpleSet();
for (int i=0; i < param.length; i++) {
declared.add(param[i]);
}
block.makeDeclaration(declared);
}
public void simplify() {

@ -22,6 +22,7 @@ import jode.decompiler.LocalInfo;
import jode.decompiler.TabbedPrintWriter;
import jode.expr.Expression;
import jode.type.Type;
import jode.util.SimpleSet;
/**
* An IfThenElseBlock is the structured block representing an if
@ -131,9 +132,9 @@ public class IfThenElseBlock extends StructuredBlock {
elseBlock.removePush();
}
public VariableSet getUsed() {
used = new VariableSet();
cond.fillInGenSet(null, used);
public SimpleSet getDeclarables() {
SimpleSet used = new SimpleSet();
cond.fillDeclarables(used);
return used;
}

@ -24,6 +24,7 @@ import jode.decompiler.LocalInfo;
import jode.expr.Expression;
import jode.expr.StoreInstruction;
import jode.expr.LocalStoreOperator;
import jode.util.SimpleSet;
/**
* This is the structured block for atomic instructions.
@ -100,7 +101,7 @@ public class InstructionBlock extends InstructionContainer {
* variable. In that case mark this as declaration and return the
* variable.
*/
public void checkDeclaration(VariableSet declareSet) {
public void checkDeclaration(SimpleSet declareSet) {
if (instr instanceof StoreInstruction
&& (((StoreInstruction)instr).getLValue()
instanceof LocalStoreOperator)) {
@ -114,7 +115,7 @@ public class InstructionBlock extends InstructionContainer {
*/
isDeclaration = true;
storeOp.getSubExpressions()[1].makeInitializer();
declareSet.removeElement(local);
declareSet.remove(local);
}
}
}
@ -125,7 +126,7 @@ public class InstructionBlock extends InstructionContainer {
* is marked as used, but not done.
* @param done The set of the already declare variables.
*/
public void makeDeclaration(VariableSet done) {
public void makeDeclaration(SimpleSet done) {
super.makeDeclaration(done);
checkDeclaration(declare);
}
@ -133,16 +134,18 @@ public class InstructionBlock extends InstructionContainer {
public void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException
{
if (instr.getType() != Type.tVoid)
writer.print("PUSH ");
else if (isDeclaration) {
if (isDeclaration) {
StoreInstruction store = (StoreInstruction) instr;
LocalInfo local =
((LocalStoreOperator) ((StoreInstruction) instr).getLValue())
.getLocalInfo();
writer.printType(local.getType().getHint());
writer.print(" ");
((LocalStoreOperator) store.getLValue()).getLocalInfo();
local.dumpDeclaration(writer);
writer.print(" = ");
store.getSubExpressions()[1].dumpExpression(writer);
} else {
if (instr.getType() != Type.tVoid)
writer.print("PUSH ");
instr.dumpExpression(writer);
}
instr.dumpExpression(writer);
writer.println(";");
}
}

@ -21,6 +21,7 @@ package jode.flow;
import jode.decompiler.LocalInfo;
import jode.expr.Expression;
import jode.expr.LocalVarOperator;
import jode.util.SimpleSet;
/**
* This is a method for block containing a single instruction.
@ -69,10 +70,10 @@ public abstract class InstructionContainer extends StructuredBlock {
instr.fillInGenSet(in, gen);
}
public VariableSet getUsed() {
used = new VariableSet();
public SimpleSet getDeclarables() {
SimpleSet used = new SimpleSet();
if (instr != null)
instr.fillInGenSet(null, used);
instr.fillDeclarables(used);
return used;
}

@ -26,6 +26,7 @@ import jode.expr.ConstOperator;
import jode.expr.StoreInstruction;
import jode.expr.LocalStoreOperator;
import jode.expr.CombineableOperator;
import jode.util.SimpleSet;
/**
* This is the structured block for an Loop block.
@ -200,25 +201,25 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
* Remove all variables from set, that we can declare inside the
* loop-block. This is the initializer for for-blocks.
*/
public void removeLocallyDeclareable(VariableSet set) {
public void removeLocallyDeclareable(SimpleSet set) {
if (type == FOR && initInstr instanceof StoreInstruction) {
StoreInstruction storeOp = (StoreInstruction) initInstr;
if (storeOp.getLValue() instanceof LocalStoreOperator) {
LocalInfo local =
((LocalStoreOperator) storeOp.getLValue()).getLocalInfo();
set.removeElement(local);
set.remove(local);
}
}
}
public VariableSet getUsed() {
used = new VariableSet();
public SimpleSet getDeclarables() {
SimpleSet used = new SimpleSet();
if (type == FOR) {
incrInstr.fillInGenSet(null, used);
incrInstr.fillDeclarables(used);
if (initInstr != null)
initInstr.fillInGenSet(null, used);
initInstr.fillDeclarables(used);
}
cond.fillInGenSet(null, used);
cond.fillDeclarables(used);
return used;
}
@ -249,7 +250,7 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
* variable. In that case mark this as declaration and return the
* variable.
*/
public void checkDeclaration(VariableSet declareSet) {
public void checkDeclaration(SimpleSet declareSet) {
if (initInstr instanceof StoreInstruction
&& (((StoreInstruction)initInstr).getLValue()
instanceof LocalStoreOperator)) {
@ -263,7 +264,7 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
*/
isDeclaration = true;
storeOp.getSubExpressions()[1].makeInitializer();
declareSet.removeElement(local);
declareSet.remove(local);
}
}
}
@ -274,7 +275,7 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
* is marked as used, but not done.
* @param done The set of the already declare variables.
*/
public void makeDeclaration(VariableSet done) {
public void makeDeclaration(SimpleSet done) {
super.makeDeclaration(done);
if (type == FOR && initInstr != null)
checkDeclaration(declare);

@ -19,6 +19,7 @@
package jode.flow;
import jode.decompiler.LocalInfo;
import jode.util.SimpleSet;
/**
* This block represents a ret instruction. A ret instruction is
@ -58,9 +59,9 @@ public class RetBlock extends StructuredBlock {
return null;
}
public VariableSet getUsed() {
used = new VariableSet();
used.addElement(local);
public SimpleSet getDeclarables() {
SimpleSet used = new SimpleSet();
used.add(local);
return used;
}

@ -22,6 +22,7 @@ import jode.decompiler.TabbedPrintWriter;
import jode.decompiler.LocalInfo;
import jode.expr.LocalStoreOperator;
import jode.expr.StoreInstruction;
import jode.util.SimpleSet;
/**
* A sequential block combines exactly two structured blocks to a new
@ -167,22 +168,23 @@ public class SequentialBlock extends StructuredBlock {
* @return all locals that are used in this block or in some sub
* block (this is <i>not</i> the used set).
*/
public VariableSet propagateUsage() {
used = new VariableSet();
VariableSet allUse = new VariableSet();
VariableSet childUse0 = subBlocks[0].propagateUsage();
VariableSet childUse1 = subBlocks[1].propagateUsage();
public SimpleSet propagateUsage() {
used = getDeclarables();
SimpleSet allUse = new SimpleSet();
SimpleSet childUse0 = subBlocks[0].propagateUsage();
SimpleSet childUse1 = subBlocks[1].propagateUsage();
/* All variables used somewhere inside both sub blocks, are
* used in this block, too.
* Also the variables used in first block are used in this
* block, except when it can be declared locally. (Note that
* subBlocks[0].used != childUse0) */
used.unionExact(subBlocks[0].used);
used.addAll(subBlocks[0].used);
if (subBlocks[0] instanceof LoopBlock)
((LoopBlock) subBlocks[0]).removeLocallyDeclareable(used);
used.unionExact(childUse0.intersectExact(childUse1));
allUse.unionExact(childUse0);
allUse.unionExact(childUse1);
allUse.addAll(childUse0);
allUse.addAll(childUse1);
childUse0.retainAll(childUse1);
used.addAll(childUse0);
return allUse;
}
@ -192,7 +194,7 @@ public class SequentialBlock extends StructuredBlock {
* is marked as used, but not done.
* @param done The set of the already declare variables.
*/
public void makeDeclaration(VariableSet done) {
public void makeDeclaration(SimpleSet done) {
super.makeDeclaration(done);
if (subBlocks[0] instanceof InstructionBlock)
/* An instruction block may declare a variable for us.

@ -22,6 +22,10 @@ import jode.AssertError;
import jode.GlobalOptions;
import jode.decompiler.TabbedPrintWriter;
import jode.decompiler.LocalInfo;
import jode.decompiler.Declarable;
import jode.util.SimpleSet;
import java.util.Enumeration;
/**
* A structured block is the building block of the source programm.
@ -63,17 +67,17 @@ public abstract class StructuredBlock {
*/
/**
* The variable set containing all variables that are used in
* this block. You must set this, before calling super.propagateUsage.
* The SimpleSet containing all Declarables that are used in this
* block.
*/
VariableSet used;
SimpleSet used;
/**
* The variable set containing all variables we must declare.
* The SimpleSet containing all Declarables we must declare.
* The analyzation is done in makeDeclaration
*/
VariableSet declare;
VariableSet done;
SimpleSet declare;
SimpleSet done;
/**
* The surrounding structured block. If this is the outermost
@ -339,8 +343,8 @@ public abstract class StructuredBlock {
return false;
}
public VariableSet getUsed() {
return new VariableSet();
public SimpleSet getDeclarables() {
return new SimpleSet();
}
/**
@ -351,17 +355,21 @@ public abstract class StructuredBlock {
*
* @return all locals that are used in this block or in some sub
* block (this is <i>not</i> the used set). */
public VariableSet propagateUsage() {
used = getUsed();
public SimpleSet propagateUsage() {
used = getDeclarables();
StructuredBlock[] subs = getSubBlocks();
VariableSet allUse = (VariableSet) used.clone();
SimpleSet allUse = (SimpleSet) used.clone();
for (int i=0; i<subs.length; i++) {
VariableSet childUse = subs[i].propagateUsage();
SimpleSet childUse = subs[i].propagateUsage();
/* All variables used in more than one sub blocks, are
* used in this block, too.
*/
used.unionExact(allUse.intersectExact(childUse));
allUse.unionExact(childUse);
Enumeration enum = childUse.elements();
SimpleSet intersection = new SimpleSet();
intersection.addAll(childUse);
intersection.retainAll(allUse);
used.addAll(intersection);
allUse.addAll(childUse);
}
return allUse;
}
@ -432,72 +440,84 @@ public abstract class StructuredBlock {
*
* @param done The set of the already declare variables.
*/
public void makeDeclaration(VariableSet done) {
this.done = (VariableSet) done.clone();
declare = new VariableSet();
public void makeDeclaration(SimpleSet done) {
// System.err.println("makeDeclaration: done = "+done);
this.done = (SimpleSet) done.clone();
declare = new SimpleSet();
java.util.Enumeration enum = used.elements();
// System.err.println("makeDeclaration: used = "+used);
next_used:
while (enum.hasMoreElements()) {
LocalInfo local = (LocalInfo) enum.nextElement();
/* First generate the names for the locals, since this may
* also change their types, if they are in the local
* variable table.
*/
String localName = local.guessName();
int size = done.size();
// Check if this local is already declared.
for (int i=0; i< size; i++) {
LocalInfo prevLocal = done.elementAt(i);
if (prevLocal.equals(local))
continue next_used;
}
// Merge with all locals in this block, that use the same
// slot and have compatible types and names.
for (int i=0; i< size; i++) {
LocalInfo prevLocal = done.elementAt(i);
if (prevLocal.getSlot() == local.getSlot()) {
/* XXX - I have to think about this...
* there may be a case where this leads to type errors.
* TODO: Give a formal proof ;-)
* One bad thing that may happen is that the name
* of prevLocal (it has already a name) doesn't match
* the intersected type.
*
* We don't want to merge variables, whose names are
* not generated by us and differ.
*
* And don't merge "this" with any other variable
* since it mustn't be written to.
*/
if (prevLocal.getType().isOfType(local.getType())
&& prevLocal.getName() != "this"
&& (prevLocal.isNameGenerated()
|| local.isNameGenerated()
|| localName.equals(prevLocal.getName()))) {
local.combineWith(prevLocal);
continue next_used;
Declarable declarable = (Declarable) enum.nextElement();
// Check if this is already declared.
if (done.contains(declarable))
continue next_used;
if (declarable instanceof LocalInfo) {
LocalInfo local = (LocalInfo) declarable;
/* First generate the names for the locals, since this may
* also change their types, if they are in the local
* variable table.
*/
String localName = local.guessName();
// Merge with all locals in this block, that use the same
// slot and have compatible types and names.
Enumeration doneEnum = done.elements();
while (doneEnum.hasMoreElements()) {
Declarable previous = (Declarable) doneEnum.nextElement();
if (!(previous instanceof LocalInfo))
continue;
LocalInfo prevLocal = (LocalInfo) previous;
if (prevLocal.getSlot() == local.getSlot()) {
/* XXX - I have to think about this...
* there may be a case where this leads to type errors.
* TODO: Give a formal proof ;-)
* One bad thing that may happen is that the name
* of prevLocal (it has already a name) doesn't match
* the intersected type.
*
* We don't want to merge variables, whose names
* are not generated by us and differ. And we
* don't want to merge special locals that have a
* constant expression, e.g. this.
*/
if (prevLocal.getType().isOfType(local.getType())
&& (prevLocal.isNameGenerated()
|| local.isNameGenerated()
|| localName.equals(prevLocal.getName()))
&& prevLocal.getExpression() == null
&& local.getExpression() == null) {
local.combineWith(prevLocal);
continue next_used;
}
}
}
}
LocalInfo previous = done.findLocal(localName);
if (previous != null) {
/* A name conflict happened. */
local.makeNameUnique();
if (declarable.getName() != null) {
Enumeration doneEnum = done.elements();
while (doneEnum.hasMoreElements()) {
Declarable previous = (Declarable) doneEnum.nextElement();
if (declarable.getName().equals(previous.getName())) {
/* A name conflict happened. */
declarable.makeNameUnique();
}
}
}
done.addElement(local);
declare.addElement(local);
done.add(declarable);
declare.add(declarable);
}
// System.err.println("makeDeclaration: declare = "+declare);
StructuredBlock[] subs = getSubBlocks();
for (int i=0; i<subs.length; i++)
subs[i].makeDeclaration(done);
/* remove the variables again, since we leave the scope.
*/
done.subtractExact(declare);
done.removeAll(declare);
}
public void checkConsistent() {
@ -569,7 +589,7 @@ public abstract class StructuredBlock {
* dumpInstruction afterwards.
* @param writer The tabbed print writer, where we print to.
*/
public void dumpSource(jode.decompiler.TabbedPrintWriter writer)
public void dumpSource(TabbedPrintWriter writer)
throws java.io.IOException
{
if ((GlobalOptions.debuggingFlags
@ -584,8 +604,9 @@ public abstract class StructuredBlock {
if (declare != null) {
java.util.Enumeration enum = declare.elements();
while (enum.hasMoreElements()) {
LocalInfo local = (LocalInfo) enum.nextElement();
dumpDeclaration(writer, local);
Declarable decl = (Declarable) enum.nextElement();
decl.dumpDeclaration(writer);
writer.println(";");
}
}
dumpInstruction(writer);
@ -594,20 +615,6 @@ public abstract class StructuredBlock {
jump.dumpSource(writer);
}
/**
* Print the code for the declaration of a local variable.
* @param writer The tabbed print writer, where we print to.
* @param local The local that should be declared.
*/
public void dumpDeclaration(jode.decompiler.TabbedPrintWriter writer, LocalInfo local)
throws java.io.IOException
{
if (!local.isRemoved()) {
writer.printType(local.getType().getHint());
writer.println(" " + local.getName().toString() + ";");
}
}
/**
* Print the instruction expressing this structured block.
* @param writer The tabbed print writer, where we print to.

@ -21,6 +21,7 @@ package jode.flow;
import jode.decompiler.LocalInfo;
import jode.decompiler.TabbedPrintWriter;
import jode.expr.Expression;
import jode.util.SimpleSet;
/**
* This class represents a synchronized structured block.
@ -70,12 +71,12 @@ public class SynchronizedBlock extends StructuredBlock {
return true;
}
public VariableSet getUsed() {
VariableSet used = new VariableSet();
public SimpleSet getDeclarables() {
SimpleSet used = new SimpleSet();
if (object != null)
object.fillInGenSet(null, used);
object.fillDeclarables(used);
else
used.addElement(local);
used.add(local);
return used;
}
@ -84,10 +85,12 @@ public class SynchronizedBlock extends StructuredBlock {
{
if (!isEntered)
writer.println("MISSING MONITORENTER");
writer.print("synchronized ("
+ (object != null
? object.toString()
: local.getName()) + ")");
writer.print("synchronized (");
if (object != null)
object.dumpExpression(writer);
else
writer.print(local.getName());
writer.print(")");
writer.openBrace();
writer.tab();
bodyBlock.dumpSource(writer);

Loading…
Cancel
Save