diff --git a/jode/jode/decompiler/CodeAnalyzer.java b/jode/jode/decompiler/CodeAnalyzer.java index 8a73a64..cdb7f97 100644 --- a/jode/jode/decompiler/CodeAnalyzer.java +++ b/jode/jode/decompiler/CodeAnalyzer.java @@ -147,7 +147,7 @@ public class CodeAnalyzer implements Analyzer, Constants { Instruction pred; try { NopOperator op = (NopOperator) ih.getInstruction(); - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); pred = ih.getInstruction(); if (pred == null) return null; @@ -168,19 +168,19 @@ public class CodeAnalyzer implements Analyzer, Constants { if (ih.getInstruction() instanceof DupOperator) /* this is not the end of the array assign */ return null; - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); ArrayStoreOperator store = (ArrayStoreOperator) ih.getInstruction(); - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); Expression lastconst = (Expression) ih.getInstruction(); - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); Expression lastindexexpr = (Expression) ih.getInstruction(); ConstOperator lastindexop = (ConstOperator) lastindexexpr.getOperator(); - if (!MyType.isOfType(lastindexop.getType(), MyType.tUInt)) + if (!MyType.isOfType(lastindexop.getType(), MyType.tInt)) return null; int lastindex = Integer.parseInt(lastindexop.getValue()); - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); DupOperator dup = (DupOperator) ih.getInstruction(); if (dup.getDepth() != 0 || dup.getCount() != store.getLValueType().stackSize()) @@ -189,12 +189,12 @@ public class CodeAnalyzer implements Analyzer, Constants { consts[lastindex] = lastconst; count = 1; while (lastindex-- > 0) { - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); ArrayStoreOperator store2 = (ArrayStoreOperator) ih.getInstruction(); - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); lastconst = (Expression) ih.getInstruction(); - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); Expression indexexpr = (Expression) ih.getInstruction(); ConstOperator indexop = (ConstOperator) indexexpr.getOperator(); @@ -210,14 +210,14 @@ public class CodeAnalyzer implements Analyzer, Constants { lastindex--; } consts[lastindex] = lastconst; - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); dup = (DupOperator) ih.getInstruction(); if (dup.getDepth() != 0 || dup.getCount() != store.getLValueType().stackSize()) return null; count++; } - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); Expression newArrayExpr = (Expression) ih.getInstruction(); NewArrayOperator newArrayOp = (NewArrayOperator) newArrayExpr.getOperator(); @@ -245,15 +245,13 @@ public class CodeAnalyzer implements Analyzer, Constants { public InstructionHeader createExpression(InstructionHeader ih) { Operator op; Expression exprs[]; - int count; + int params; try { op = (Operator) ih.getInstruction(); - int params = op.getOperandCount(); + params = op.getOperandCount(); exprs = new Expression[params]; - count = 1; for (int i = params-1; i>=0; i--) { - count++; - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); exprs[i] = (Expression) ih.getInstruction(); if (exprs[i].isVoid()) { if (i == params-1) @@ -263,6 +261,7 @@ public class CodeAnalyzer implements Analyzer, Constants { return null; i++; exprs[i] = e; + ih.combine(2, e); } } } catch (NullPointerException ex) { @@ -270,7 +269,7 @@ public class CodeAnalyzer implements Analyzer, Constants { } catch (ClassCastException ex) { return null; } - ih.combine(count, new Expression(op, exprs)); + ih.combine(params+1, new Expression(op, exprs)); return ih; } @@ -303,7 +302,7 @@ public class CodeAnalyzer implements Analyzer, Constants { StoreInstruction store; try { store = (StoreInstruction) ih.getInstruction(); - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); DupOperator dup = (DupOperator) ih.getInstruction(); if (dup.getDepth() != store.getLValueOperandCount() && @@ -337,7 +336,7 @@ public class CodeAnalyzer implements Analyzer, Constants { return null; if (iinc.getValue().equals("-1")) op ^= 1; - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); Expression loadExpr = (Expression) ih.getInstruction(); LocalLoadOperator load = (LocalLoadOperator)loadExpr.getOperator(); @@ -363,7 +362,7 @@ public class CodeAnalyzer implements Analyzer, Constants { store = (StoreInstruction) ih.getInstruction(); if (store.getLValueOperandCount() == 0) return null; - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); BinaryOperator binOp = (BinaryOperator) ih.getInstruction(); if (binOp.getOperator() == store.ADD_OP) op = Operator.INC_OP; @@ -371,7 +370,7 @@ public class CodeAnalyzer implements Analyzer, Constants { op = Operator.DEC_OP; else return null; - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); Expression expr = (Expression) ih.getInstruction(); ConstOperator constOp = (ConstOperator) expr.getOperator(); if (!constOp.getValue().equals("1") && @@ -379,18 +378,18 @@ public class CodeAnalyzer implements Analyzer, Constants { return null; if (constOp.getValue().equals("-1")) op ^= 1; - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); DupOperator dup = (DupOperator) ih.getInstruction(); if (dup.getCount() != store.getLValueType().stackSize() || dup.getDepth() != store.getLValueOperandCount()) return null; - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); Operator load = (Operator) ih.getInstruction(); if (!store.matches(load)) return null; - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); DupOperator dup2 = (DupOperator) ih.getInstruction(); if (dup2.getCount() != store.getLValueOperandCount() || dup2.getDepth() != 0) @@ -413,20 +412,20 @@ public class CodeAnalyzer implements Analyzer, Constants { BinaryOperator binop; try { store = (StoreInstruction) ih.getInstruction(); - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); binop = (BinaryOperator) ih.getInstruction(); if (binop.getOperator() < binop.ADD_OP || binop.getOperator() >= binop.ASSIGN_OP) return null; - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); rightHandSide = (Expression) ih.getInstruction(); if (rightHandSide.isVoid()) return null; /* XXX */ - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); Operator load = (Operator) ih.getInstruction(); if (!store.matches(load)) return null; - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); DupOperator dup = (DupOperator) ih.getInstruction(); if (dup.getDepth() != 0 && dup.getCount() != store.getLValueOperandCount()) @@ -455,16 +454,16 @@ public class CodeAnalyzer implements Analyzer, Constants { int params = constrCall.getOperandCount(); exprs = new Expression[params]; for (int i = params-1; i>0; i--) { - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); exprs[i] = (Expression) ih.getInstruction(); if (exprs[i].isVoid()) return null; /* XXX */ } - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); DupOperator dup = (DupOperator) ih.getInstruction(); if (dup.getCount() != 1 && dup.getDepth() != 0) return null; - ih = ih.getUniquePredecessor(); + ih = ih.getSimpleUniquePredecessor(); exprs[0] = (Expression) ih.getInstruction(); if (exprs[0].isVoid()) return null; @@ -493,7 +492,7 @@ public class CodeAnalyzer implements Analyzer, Constants { return null; InstructionHeader[] dests2 = ih2.getSuccessors(); - /* if ih2.getUniquePredecessor.getOperator().isVoid() XXX */ + /* if ih2.getSimpleUniquePredecessor.getOperator().isVoid() XXX */ Vector predec = ih2.getPredecessors(); if (predec.size() != 1) @@ -510,12 +509,12 @@ public class CodeAnalyzer implements Analyzer, Constants { e = new Expression[2]; operator = Operator.LOG_AND_OP; e[1] = (Expression)ih2.getInstruction(); - e[0] = ((Expression)ih2.getInstruction()).negate(); + e[0] = ((Expression)ih1.getInstruction()).negate(); } else if (dests1[1] == dests2[1]) { e = new Expression[2]; operator = Operator.LOG_OR_OP; e[1] = (Expression)ih2.getInstruction(); - e[0] = (Expression)ih2.getInstruction(); + e[0] = (Expression)ih1.getInstruction(); } else return null; } catch (ClassCastException ex) { @@ -531,6 +530,64 @@ public class CodeAnalyzer implements Analyzer, Constants { return ih1; } + public InstructionHeader createFunnyIfThenElseOp(InstructionHeader ih) { + Expression cond = null; + try { + InstructionHeader ifHeader= ih; + if (ifHeader.switchType != MyType.tBoolean) + return null; + CompareUnaryOperator compare = + (CompareUnaryOperator) ifHeader.getInstruction(); + if ((compare.getOperator() & ~1) != compare.EQUALS_OP) + return null; + Enumeration enum = ih.getPredecessors().elements(); + while (enum.hasMoreElements()) { + try { + ih = (InstructionHeader) enum.nextElement(); + Expression zeroExpr = (Expression) ih.getInstruction(); + ConstOperator zero = + (ConstOperator) zeroExpr.getOperator(); + if (!zero.getValue().equals("0")) + continue; + + ih = ih.getUniquePredecessor(); + if (ih.switchType != MyType.tBoolean) + continue; + + if (compare.getOperator() == compare.EQUALS_OP && + ih.getSuccessors()[1] != ifHeader.getSuccessors()[0] + || compare.getOperator() == compare.NOTEQUALS_OP && + ih.getSuccessors()[1] != ifHeader.getSuccessors()[1]) + continue; + + cond = (Expression) ih.getInstruction(); + break; + } catch (ClassCastException ex) { + } catch (NullPointerException ex) { + } + } + + if (cond == null) + return null; + + } catch (ClassCastException ex) { + return null; + } catch (NullPointerException ex) { + return null; + } + + InstructionHeader next = ih.nextInstruction; + ih.nextInstruction = next.nextInstruction; + ih.successors[1].predecessors.removeElement(ih); + ih.switchType = MyType.tVoid; + ih.successors = next.successors; + ih.successors[0].predecessors.removeElement(next); + ih.successors[0].predecessors.addElement(ih); + ih.succs = next.succs; + ih.length += next.length; + return ih; + } + public InstructionHeader createIfThenElseOperator(InstructionHeader ih) { InstructionHeader ifHeader; Expression e[] = new Expression[3]; @@ -551,7 +608,7 @@ public class CodeAnalyzer implements Analyzer, Constants { succs[0].getSuccessors()[0] != succs[1].getSuccessors()[0]) return null; - e[0] = (Expression) ifHeader.getInstruction(); + e[0] = ((Expression) ifHeader.getInstruction()).negate(); e[1] = (Expression) succs[0].getInstruction(); e[2] = (Expression) succs[1].getInstruction(); } catch (ClassCastException ex) { @@ -563,11 +620,13 @@ public class CodeAnalyzer implements Analyzer, Constants { (MyType.intersection(e[1].getType(),e[2].getType())); ifHeader.instr = new Expression(iteo, e); ifHeader.nextInstruction = ih.nextInstruction; + ifHeader.length = ih.addr + ih.length - ifHeader.addr; + ifHeader.succs = ih.succs; ifHeader.successors = ih.successors; ifHeader.switchType = Type.tVoid; - ifHeader.nextInstruction.predecessors.removeElement(succs[0]); - ifHeader.nextInstruction.predecessors.removeElement(succs[1]); - ifHeader.nextInstruction.predecessors.addElement(ifHeader); + ifHeader.successors[0].predecessors.removeElement(succs[0]); + ifHeader.successors[0].predecessors.removeElement(succs[1]); + ifHeader.successors[0].predecessors.addElement(ifHeader); return ifHeader; } @@ -578,6 +637,7 @@ public class CodeAnalyzer implements Analyzer, Constants { ih = next) { if (env.isVerbose) System.err.print("."); +// System.err.println(""+ih.getAddress()); if ((next = removeNop(ih)) != null) continue; if ((next = createExpression(ih)) != null) continue; if ((next = createPostIncExpression(ih)) != null) continue; @@ -585,6 +645,7 @@ public class CodeAnalyzer implements Analyzer, Constants { if ((next = createAssignOp(ih)) != null) continue; if ((next = combineNewConstructor(ih)) != null) continue; if ((next = combineIfGotoExpressions(ih)) != null) continue; + if ((next = createFunnyIfThenElseOp(ih)) != null) continue; if ((next = createIfThenElseOperator(ih)) != null) continue; if ((next = createAssignExpression(ih)) != null) continue; if ((next = createConstantArray(ih)) != null) continue; diff --git a/jode/jode/decompiler/LocalInfo.java b/jode/jode/decompiler/LocalInfo.java index 96199d8..dbf7ced 100644 --- a/jode/jode/decompiler/LocalInfo.java +++ b/jode/jode/decompiler/LocalInfo.java @@ -92,7 +92,7 @@ public class LocalInfo { */ public Type setType(Type newType) { if (shadow != null) - return shadow.setType(type); + return shadow.setType(newType); this.type = MyType.intersection(this.type, newType); if (this.type == MyType.tError) System.err.println("Type error in "+name.toString()); diff --git a/jode/jode/decompiler/LocalVariableAnalyzer.java b/jode/jode/decompiler/LocalVariableAnalyzer.java index 7034165..c9c8ab7 100644 --- a/jode/jode/decompiler/LocalVariableAnalyzer.java +++ b/jode/jode/decompiler/LocalVariableAnalyzer.java @@ -196,11 +196,16 @@ public class LocalVariableAnalyzer { throws java.io.IOException { Enumeration enum = locals.elements(); + VAR: while (enum.hasMoreElements()) { LocalInfo li = (LocalInfo) enum.nextElement(); - if (!li.isShadow()) + if (!li.isShadow()) { + for (int i=0; i< argLocals.length; i++) + if (argLocals[i].getLocalInfo() == li) + continue VAR; writer.println(env.getTypeString(li.getType(), li.getName())+";"); + } } } } diff --git a/jode/jode/expr/ArrayLoadOperator.java b/jode/jode/expr/ArrayLoadOperator.java index 8a4d433..2afaa27 100644 --- a/jode/jode/expr/ArrayLoadOperator.java +++ b/jode/jode/expr/ArrayLoadOperator.java @@ -34,10 +34,12 @@ public class ArrayLoadOperator extends SimpleOperator { public void setOperandType(Type[] t) { super.setOperandType(t); -// if (operandTypes[0] instanceof ArrayType) + try { type = operandTypes[0].getElementType(); -// else -// type = Type.tError; + } catch (sun.tools.java.CompilerError err) { + System.err.println("No Array type: "+operandTypes[0]); + type = Type.tError; + } } public String toString(String[] operands) { diff --git a/jode/jode/expr/ArrayStoreOperator.java b/jode/jode/expr/ArrayStoreOperator.java index ab6b4c2..2cc4462 100644 --- a/jode/jode/expr/ArrayStoreOperator.java +++ b/jode/jode/expr/ArrayStoreOperator.java @@ -36,7 +36,6 @@ public class ArrayStoreOperator extends StoreInstruction { */ public boolean setLValueType(Type type) { this.lvalueType = type; - System.err.println("Setting Lvalue type to "+lvalueType); return true; } @@ -54,6 +53,7 @@ public class ArrayStoreOperator extends StoreInstruction { try { lvalueType = arrayType.getElementType(); } catch (sun.tools.java.CompilerError err) { + System.err.println("No Array type: "+arrayType); lvalueType = Type.tError; } } diff --git a/jode/jode/expr/ConstOperator.java b/jode/jode/expr/ConstOperator.java index d6a7eb8..4e06b90 100644 --- a/jode/jode/expr/ConstOperator.java +++ b/jode/jode/expr/ConstOperator.java @@ -46,7 +46,7 @@ public class ConstOperator extends NoArgOperator { } public String toString(String[] operands) { - if (type == Type.tString) + if (MyType.isOfType(type, Type.tString)) return quoted(value); if (type == Type.tBoolean) { if (value.equals("0")) diff --git a/jode/jode/expr/ConstructorOperator.java b/jode/jode/expr/ConstructorOperator.java index 2584adc..f9653ed 100644 --- a/jode/jode/expr/ConstructorOperator.java +++ b/jode/jode/expr/ConstructorOperator.java @@ -25,8 +25,8 @@ public class ConstructorOperator extends Operator { public Type getOperandType(int i) { if (i == 0) - return type; - return field.getType().getArgumentTypes()[i-1]; + return MyType.tSubType(type); + return MyType.tSubType(field.getType().getArgumentTypes()[i-1]); } public void setOperandType(Type types[]) { diff --git a/jode/jode/expr/Expression.java b/jode/jode/expr/Expression.java index 5e69dc9..2f1cd96 100644 --- a/jode/jode/expr/Expression.java +++ b/jode/jode/expr/Expression.java @@ -52,7 +52,7 @@ public class Expression extends Instruction { if (e.operator instanceof StoreInstruction) { StoreInstruction store = (StoreInstruction) e.operator; Expression search = this; - while (search.subExpressions.length > 0) { + while (true) { if (store.matches(search.operator)) { int i; for (i=0; i < e.subExpressions.length-1; i++) { @@ -62,12 +62,20 @@ public class Expression extends Instruction { } if (i == e.subExpressions.length-1) { search.operator = - new AssignOperator(store.getOperator(), store); + new AssignOperator(store.getOperator(), store); search.subExpressions = e.subExpressions; return this; } } - search = search.subExpressions[0]; + if (search.subExpressions.length == 0) + break; + if (search.getOperator() instanceof AssignOperator) + search = search.subExpressions[subExpressions.length-1]; + else if (search.getOperator() instanceof StringAddOperator && + search.subExpressions[1] == emptyString) + search = search.subExpressions[1]; + else + search = search.subExpressions[0]; } } return null; @@ -107,9 +115,8 @@ public class Expression extends Instruction { if (operator.getPriority() < minPriority) { result = "("+result+")"; } - if (operator.casts.indexOf("/*",0) >= 0 || - operator.casts.indexOf("<-",0) >= 0 && false) - result = "<"+operator.casts+" "+result+">"; + if (operator.getType() == MyType.tError) + result = "(/*type error */" + result+")"; return result; } @@ -134,12 +141,16 @@ public class Expression extends Instruction { return toString(0); } + static Expression emptyString = + new Expression(new EmptyStringOperator(), new Expression[0]); + Expression simplifyStringBuffer() { FieldDefinition field; if (operator instanceof InvokeOperator && (field = ((InvokeOperator)operator).getField()) .getClassDefinition().getName() == Constants.idJavaLangStringBuffer && + !((InvokeOperator)operator).isStatic() && field.getName() == Constants.idAppend && field.getType().getArgumentTypes().length == 1) { @@ -148,20 +159,21 @@ public class Expression extends Instruction { return null; if (e.operator instanceof EmptyStringOperator && - subExpressions[1].getType() == Type.tString) + MyType.isOfType(subExpressions[1].getType(), Type.tString)) return subExpressions[1]; - Expression[] exprs = { e, subExpressions[1] }; + Expression[] exprs = { e, + (Expression)subExpressions[1].simplify() }; return new Expression(new StringAddOperator(), exprs); } if (operator instanceof ConstructorOperator && - operator.getType() == MyType.tStringBuffer) { + MyType.isOfType(operator.getType(), MyType.tStringBuffer)) { if (operator.getOperandCount() == 1) - return new Expression(new EmptyStringOperator(), - new Expression[0]); + return emptyString; else if (operator.getOperandCount() == 2 && - subExpressions[1].getType() == MyType.tString) - return subExpressions[1]; + MyType.isOfType(subExpressions[1].getType(), + MyType.tString)) + return (Expression) subExpressions[1].simplify(); } return null; } @@ -210,14 +222,31 @@ public class Expression extends Instruction { if (operator instanceof InvokeOperator && ((InvokeOperator)operator).getField(). getName() == Constants.idToString && + !((InvokeOperator)operator).isStatic() && ((InvokeOperator)operator).getField(). getClassDefinition().getType() == MyType.tStringBuffer && operator.getOperandCount() == 1) { - Expression e = subExpressions[0].simplifyStringBuffer(); - if (e != null) - return e.simplify(); + Instruction simple = subExpressions[0].simplifyStringBuffer(); + if (simple != null) + return simple; + } + if (operator instanceof InvokeOperator && + ((InvokeOperator)operator).getField(). + getName() == Constants.idValueOf && + ((InvokeOperator)operator).isStatic() && + ((InvokeOperator)operator).getField(). + getClassDefinition().getType() == MyType.tString && + operator.getOperandCount() == 1) { + if (subExpressions[0].getType() == MyType.tString) + return subExpressions[0].simplify(); + else { + Expression[] exprs = { + emptyString, + (Expression) subExpressions[0].simplify() + }; + return new Expression(new StringAddOperator(), exprs); + } } - for (int i=0; i< subExpressions.length; i++) subExpressions[i] = (Expression) subExpressions[i].simplify(); diff --git a/jode/jode/expr/InstructionHeader.java b/jode/jode/expr/InstructionHeader.java index 076cab3..94ec185 100644 --- a/jode/jode/expr/InstructionHeader.java +++ b/jode/jode/expr/InstructionHeader.java @@ -160,9 +160,18 @@ public class InstructionHeader { if (predecessors.size() != 1) return null; InstructionHeader pre = (InstructionHeader)predecessors.elementAt(0); - return (pre.getNextInstruction() == this && - pre.getSuccessors().length != 1) ? null : pre; + return (pre.getNextInstruction() == this) ? pre : null; } + + /** + * Get the unique predecessor which mustn't be a (un)conditional jump + * @return the predecessor or null if there isn't a such a thing + */ + public InstructionHeader getSimpleUniquePredecessor() { + InstructionHeader pre = getUniquePredecessor(); + return (pre.getSuccessors().length != 1) ? null : pre; + } + /** * Get the predecessors of this instruction. This function mustn't @@ -199,6 +208,15 @@ public class InstructionHeader { writer.println("<"+addr + " - "+(addr+length-1)+">"); writer.tab(); } + +// writer.print("predecs: "); +// for (int i=0; i0) writer.print(", "); +// writer.print(""+((InstructionHeader)predecessors.elementAt(i)). +// getAddress()); +// } +// writer.println(""); + if (!hasDirectPredecessor() && addr != 0) writer.print("addr_"+addr+": "); diff --git a/jode/jode/expr/InvokeOperator.java b/jode/jode/expr/InvokeOperator.java index 6f9274c..319ab95 100644 --- a/jode/jode/expr/InvokeOperator.java +++ b/jode/jode/expr/InvokeOperator.java @@ -17,6 +17,10 @@ public class InvokeOperator extends Operator { this.field = field; } + public boolean isStatic() { + return staticFlag; + } + public FieldDefinition getField() { return field; } diff --git a/jode/jode/expr/LocalLoadOperator.java b/jode/jode/expr/LocalLoadOperator.java index 505417e..54af9ae 100644 --- a/jode/jode/expr/LocalLoadOperator.java +++ b/jode/jode/expr/LocalLoadOperator.java @@ -29,12 +29,12 @@ implements LocalVarOperator { } public Type getType() { - System.err.println("LocalLoad.getType of "+local.getName()+": "+local.getType()); +// System.err.println("LocalLoad.getType of "+local.getName()+": "+local.getType()); return local.getType(); } public boolean setType(Type type) { - System.err.println("LocalLoad.setType of "+local.getName()+": "+local.getType()); +// System.err.println("LocalLoad.setType of "+local.getName()+": "+local.getType()); return super.setType(local.setType(type)); } diff --git a/jode/jode/expr/LocalStoreOperator.java b/jode/jode/expr/LocalStoreOperator.java index 1677ff9..118be47 100644 --- a/jode/jode/expr/LocalStoreOperator.java +++ b/jode/jode/expr/LocalStoreOperator.java @@ -29,12 +29,12 @@ implements LocalVarOperator { } public Type getLValueType() { - System.err.println("LocalStore.getType of "+local.getName()+": "+local.getType()); +// System.err.println("LocalStore.getType of "+local.getName()+": "+local.getType()); return local.getType(); } public boolean setLValueType(Type type) { - System.err.println("LocalStore.setType of "+local.getName()+": "+local.getType()); +// System.err.println("LocalStore.setType of "+local.getName()+": "+local.getType()); return super.setLValueType (local.setType(MyType.tSuperType(type))); } diff --git a/jode/jode/expr/Operator.java b/jode/jode/expr/Operator.java index 9aa46fe..6e6bef4 100644 --- a/jode/jode/expr/Operator.java +++ b/jode/jode/expr/Operator.java @@ -11,6 +11,8 @@ public abstract class Operator extends Instruction { public final static int INC_OP = 24; /* must be even! */ public final static int DEC_OP = 25; public final static int COMPARE_OP = 26; /* must be even! */ + public final static int EQUALS_OP = 26; + public final static int NOTEQUALS_OP = 27; public final static int LOG_AND_OP = 32; /* must be even! */ public final static int LOG_OR_OP = 33; public final static int LOG_NOT_OP = 34; @@ -26,14 +28,11 @@ public abstract class Operator extends Instruction { protected int operator; - String casts; - Operator (Type type, int op) { super(type); this.operator = op; if (type == null) throw new AssertError("type == null"); - casts = type.toString(); } public int getOperator() { @@ -48,12 +47,7 @@ public abstract class Operator extends Instruction { * @return true if the operand types changed */ public boolean setType(Type type) { -// if (!MyType.isOfType(type, this.type)) { -// casts = type.toString()+"/*invalid*/ <- " + casts; -// } else if (type != this.type) { -// casts = type.toString()+" <- " + casts; -// } -// this.type = type; + this.type = type; return false; } diff --git a/jode/jode/expr/ReturnOperator.java b/jode/jode/expr/ReturnOperator.java index cea0b47..36e5f01 100644 --- a/jode/jode/expr/ReturnOperator.java +++ b/jode/jode/expr/ReturnOperator.java @@ -5,9 +5,9 @@ public class ReturnOperator extends SimpleOperator { public ReturnOperator(Type type) { super(Type.tVoid, 0, (type == Type.tVoid)?0:1); if (type != Type.tVoid) - operandTypes[0] = type; + operandTypes[0] = MyType.tSubType(type); } - + public int getPriority() { return 0; } diff --git a/jode/jode/expr/SwapOperator.java b/jode/jode/expr/SwapOperator.java index de95061..dd66439 100644 --- a/jode/jode/expr/SwapOperator.java +++ b/jode/jode/expr/SwapOperator.java @@ -2,7 +2,7 @@ package jode; public class SwapOperator extends Instruction { public SwapOperator() { - super(MyType.tError); + super(MyType.tVoid); } public String toString() diff --git a/jode/jode/type/ClassRangeType.java b/jode/jode/type/ClassRangeType.java index 050c985..dba967c 100644 --- a/jode/jode/type/ClassRangeType.java +++ b/jode/jode/type/ClassRangeType.java @@ -36,6 +36,13 @@ public class ClassRangeType extends MyType { // Fahrzeug, Fahrrad // int , Fahrrad error + if (bottom != null && bottom.getTypeCode() == 103) { + bottom = ((ClassRangeType)bottom).bottomType; + } + if (top != null && top.getTypeCode() == 103) { + top = ((ClassRangeType)top).topType; + } + /* First the trivial cases */ if (top == tError || bottom == tError) @@ -49,13 +56,31 @@ public class ClassRangeType extends MyType { /* -> * if bottom is tObject, its okay. */ - if (bottom == null || bottom == tObject) + + if (bottom == top) + return bottom; + + if (top.getTypeCode() <= 4 && bottom == null) + return top; + + if (bottom != null && bottom.getTypeCode() <= 4 && + top.getTypeCode() <= bottom.getTypeCode()) + return bottom; + + if (top.getTypeCode() != 9 && top.getTypeCode() != 10) + return tError; + + if (bottom == null || bottom == tObject) return new ClassRangeType(tObject, top); /* now bottom != null and top != null */ - if (bottom.getTypeCode() == 9 && top.getTypeCode() == 9) - return tArray(createRangeType(bottom.getElementType(), - top.getElementType())); + if (bottom.getTypeCode() == 9 && top.getTypeCode() == 9) { + Type type = createRangeType(bottom.getElementType(), + top.getElementType()); + if (type == tError) + return tError; + return tArray(type); + } if (bottom.getTypeCode() != 10 || top.getTypeCode() != 10) return tError; @@ -129,7 +154,7 @@ public class ClassRangeType extends MyType { return tArray(getSpecializedType(t1.getElementType(), t2.getElementType())); - if (t1.getTypeCode() != 10 && t2.getTypeCode() != 10) + if (t1.getTypeCode() != 10 || t2.getTypeCode() != 10) return tError; /* Now we have two classes or interfaces. The result should @@ -171,8 +196,8 @@ public class ClassRangeType extends MyType { * Since the while condition is moved to the bottom of * the loop, the type information of foo is only available * after the two interface methods are called. - * The current code would produce tError. */ - + * The current code would produce tError. + */ ClassDeclaration c1 = new ClassDeclaration(t1.getClassName()); ClassDeclaration c2 = new ClassDeclaration(t2.getClassName()); @@ -182,10 +207,10 @@ public class ClassRangeType extends MyType { return t2; if (c2.getClassDefinition(env).superClassOf(env, c1)) return t1; -// if (c1.getClassDefinition(env).implementedBy(env, c2)) -// return t2; -// if (c2.getClassDefinition(env).implementedBy(env, c1)) -// return t1; + if (c1.getClassDefinition(env).implementedBy(env, c2)) + return t2; + if (c2.getClassDefinition(env).implementedBy(env, c1)) + return t1; } catch (ClassNotFound ex) { } return tError; @@ -231,7 +256,7 @@ public class ClassRangeType extends MyType { return tArray(getGeneralizedType(t1.getElementType(), t2.getElementType())); - if (t1.getTypeCode() != 10 && t2.getTypeCode() != 10) + if (t1.getTypeCode() != 10 || t2.getTypeCode() != 10) return tError; /* This code is not always correct: @@ -264,14 +289,14 @@ public class ClassRangeType extends MyType { ClassDeclaration c2 = new ClassDeclaration(t2.getClassName()); try { -// /* if one of the two types is an interface which -// * is implemented by the other type the interface -// * is the result. -// */ -// if (c1.getClassDefinition(env).implementedBy(env, c2)) -// return t1; -// if (c2.getClassDefinition(env).implementedBy(env, c1)) -// return t2; + /* if one of the two types is an interface which + * is implemented by the other type the interface + * is the result. + */ + if (c1.getClassDefinition(env).implementedBy(env, c2)) + return t1; + if (c2.getClassDefinition(env).implementedBy(env, c1)) + return t2; ClassDefinition c = c1.getClassDefinition(env); while(c != null && !c.superClassOf(env, c2)) { @@ -289,14 +314,12 @@ public class ClassRangeType extends MyType { Type bottom = getSpecializedType(bottomType, type.bottomType); Type top = getGeneralizedType(topType, type.topType); - System.err.println("intersecting "+ this +" and "+ type + - " to <" + bottom + "-" + top + ">"); - try { - throw new AssertError("in:"); - } catch(AssertError error) { - error.printStackTrace(); - } - return createRangeType(bottom,top); + Type newType = createRangeType(bottom,top); + if (newType == tError) + System.err.println("intersecting "+ this +" and "+ type + + " to <" + bottom + "-" + top + + "> to "); + return newType; } public boolean intersects(ClassRangeType type) diff --git a/jode/jode/type/MyType.java b/jode/jode/type/MyType.java index df9fe3d..4d37446 100644 --- a/jode/jode/type/MyType.java +++ b/jode/jode/type/MyType.java @@ -94,7 +94,7 @@ public class MyType extends Type { * @return the intersection, or tError, if a type conflict happens. */ public static Type intersection(Type t1, Type t2) { - System.err.println("intersecting "+ t1 +" and "+ t2); +// System.err.println("intersecting "+ t1 +" and "+ t2); /* Trivial cases first. */ if (t1 == t2 || t2 == tUnknown) @@ -123,10 +123,11 @@ public class MyType extends Type { /* Now it must be a class range type, or we have lost! */ - if (t1.getTypeCode() != 103 || t2.getTypeCode() != 103) - throw new AssertError("Types incompatible: "+ - t1.toString()+","+ t2.toString()); -// return tError; + if (t1.getTypeCode() != 103 || t2.getTypeCode() != 103) { + System.err.println("intersecting "+ t1 +" and "+ t2 + + " to "); + return tError; + } return ((ClassRangeType)t1).getIntersection((ClassRangeType)t2); } @@ -140,60 +141,13 @@ public class MyType extends Type { } /** - * Check if t1 is in <unknown -- t2&rt;. - * @return true if t1 is a more specific type than t2, e.g. - * if t2 is a superclass of t1 - * @deprecated think about it, you don't need it! (I think) - * this code is probably broken so don't use it! + * Check if t1 and <unknown -- t2&rt; are not disjunct. + * @param t1 the type that should be checked + * @param t2 a simple type; this mustn't be a range type. + * @return true if this is the case. */ public static boolean isOfType(Type t1, Type t2) { - if ((t1 == t2 || t2 == tUnknown) && t1 != tError) - return true; - - switch (t1.getTypeCode()) { - case 0: /* boolean*/ - case 1: /* byte */ - case 2: /* char */ - case 3: /* short */ - case 4: /* int */ - - /* JavaC thinks, that this is okay. */ - if (t2.getTypeCode() >= 0 && t2.getTypeCode() <=4) - return true; - -// /* fallthrough */ -// case 104: /* unknown index */ -// if (t2 == tUInt) -// return true; - break; - - case 5: /* long */ - case 6: /* float */ - case 7: /* double */ - case 8: /* null? */ - case 11: /* void */ - case 12: /* method */ - case 13: /* error */ -// case 101: /* unknown int */ - /* This are only to themself compatible */ - break; - - case 9: /* array */ - case 10: /* class */ - t1 = new ClassRangeType(t1, null); - /* fall through */ - case 103: /* class range type */ - if (t2.getTypeCode() == 103) - return ((ClassRangeType)t1).intersects((ClassRangeType)t2); - - if (t2.getTypeCode() == 9 || t2.getTypeCode() == 10) - return ((ClassRangeType)t1). - intersects(new ClassRangeType(t2, null)); - break; - - default: - throw new AssertError("Wrong typeCode "+t1.getTypeCode()); - } - return false; + return (ClassRangeType.getGeneralizedType(t1,t2) == t2 && + ClassRangeType.getSpecializedType(t1,t2) == t2); } }