Issue #258 AS1/2 chained assignments

AS1/2 Detecting temporary registers
assignment spaces
This commit is contained in:
Jindra Petk
2013-07-31 22:21:50 +02:00
parent 25efe3793f
commit c63fd4ebd9
21 changed files with 193 additions and 30 deletions

View File

@@ -640,7 +640,7 @@ public class AVM2Graph extends Graph {
}
@Override
protected void finalProcess(List<GraphTargetItem> list, int level) {
protected void finalProcess(List<GraphTargetItem> list, int level, List<Object> localData) {
if (level == 0) {
if (!list.isEmpty()) {
if (list.get(list.size() - 1) instanceof ReturnVoidAVM2Item) {

View File

@@ -38,7 +38,7 @@ public class InitPropertyAVM2Item extends AVM2Item implements SetTypeAVM2Item, A
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
return formatProperty(constants, object, propertyName, localRegNames, fullyQualifiedNames) + hilight("=") + value.toString(constants, localRegNames, fullyQualifiedNames);
return formatProperty(constants, object, propertyName, localRegNames, fullyQualifiedNames) + hilight(" = ") + value.toString(constants, localRegNames, fullyQualifiedNames);
}
@Override

View File

@@ -36,7 +36,7 @@ public class SetLocalAVM2Item extends AVM2Item implements SetTypeAVM2Item, Assig
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
return hilight(localRegName(localRegNames, regIndex) + "=") + value.toString(constants, localRegNames, fullyQualifiedNames);
return hilight(localRegName(localRegNames, regIndex) + " = ") + value.toString(constants, localRegNames, fullyQualifiedNames);
}
@Override

View File

@@ -44,7 +44,7 @@ public class SetPropertyAVM2Item extends AVM2Item implements SetTypeAVM2Item, As
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
return formatProperty(constants, object, propertyName, localRegNames, fullyQualifiedNames) + hilight("=") + value.toString(constants, localRegNames, fullyQualifiedNames);
return formatProperty(constants, object, propertyName, localRegNames, fullyQualifiedNames) + hilight(" = ") + value.toString(constants, localRegNames, fullyQualifiedNames);
}
@Override

View File

@@ -46,7 +46,7 @@ public class SetSlotAVM2Item extends AVM2Item implements SetTypeAVM2Item, Assign
@Override
public String toString(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {
return getName(constants, localRegNames, fullyQualifiedNames) + hilight("=") + value.toString(constants, localRegNames, fullyQualifiedNames);
return getName(constants, localRegNames, fullyQualifiedNames) + hilight(" = ") + value.toString(constants, localRegNames, fullyQualifiedNames);
}
public String getName(ConstantPool constants, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) {

View File

@@ -48,7 +48,7 @@ public class SetSuperAVM2Item extends AVM2Item {
if (Highlighting.stripHilights(calee).equals("this.")) {
calee = "";
}
return calee + hilight("super.") + propertyName.toString(constants, localRegNames, fullyQualifiedNames) + hilight("=") + value.toString(constants, localRegNames, fullyQualifiedNames);
return calee + hilight("super.") + propertyName.toString(constants, localRegNames, fullyQualifiedNames) + hilight(" = ") + value.toString(constants, localRegNames, fullyQualifiedNames);
}
@Override

View File

@@ -48,7 +48,9 @@ import com.jpexs.decompiler.graph.model.SwitchItem;
import com.jpexs.decompiler.graph.model.WhileItem;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Stack;
/**
@@ -92,7 +94,13 @@ public class ActionGraph extends Graph {
}
@Override
protected void finalProcess(List<GraphTargetItem> list, int level) {
protected void finalProcess(List<GraphTargetItem> list, int level, List<Object> localData) {
if (localData.isEmpty()) {
localData.add(new HashSet<Integer>()); //List of temporaryRegisters
}
@SuppressWarnings("unchecked")
Set<Integer> temporaryRegisters = (HashSet<Integer>) localData.get(0);
List<GraphTargetItem> ret = Action.checkClass(list);
if (ret != list) {
list.clear();
@@ -184,6 +192,7 @@ public class ActionGraph extends Graph {
}
}
//detectChained(list, temporaryRegisters);
}
@Override

View File

@@ -42,7 +42,7 @@ public class DecrementActionItem extends ActionItem {
@Override
public String toString(ConstantPool constants) {
return object.toString(constants) + hilight("-1");
return object.toString(constants) + hilight(" - 1");
}
@Override

View File

@@ -34,6 +34,9 @@ public class DefineLocalActionItem extends ActionItem implements SetTypeActionIt
public List<GraphTargetItem> getAllSubItems() {
List<GraphTargetItem> ret = new ArrayList<>();
ret.add(name);
if (value != null) {
ret.add(value);
}
return ret;
}

View File

@@ -42,7 +42,7 @@ public class IncrementActionItem extends ActionItem {
@Override
public String toString(ConstantPool constants) {
return object.toString(constants) + hilight("+1");
return object.toString(constants) + hilight(" + 1");
}
@Override

View File

@@ -79,9 +79,9 @@ public class SetMemberActionItem extends ActionItem implements SetTypeActionItem
public String toString(ConstantPool constants) {
if (!((objectName instanceof DirectValueActionItem) && (((DirectValueActionItem) objectName).value instanceof String))) {
//if(!(functionName instanceof GetVariableActionItem))
return object.toString(constants) + "[" + stripQuotes(objectName, constants) + "]" + "=" + value.toString(constants);
return object.toString(constants) + "[" + stripQuotes(objectName, constants) + "]" + " = " + value.toString(constants);
}
return object.toString(constants) + "." + stripQuotes(objectName, constants) + "=" + value.toString(constants);
return object.toString(constants) + "." + stripQuotes(objectName, constants) + " = " + value.toString(constants);
}
@Override

View File

@@ -70,9 +70,9 @@ public class SetPropertyActionItem extends ActionItem implements SetTypeActionIt
@Override
public String toString(ConstantPool constants) {
if (isEmptyString(target)) {
return hilight(Action.propertyNames[propertyIndex] + "=") + value.toString(constants);
return hilight(Action.propertyNames[propertyIndex] + " = ") + value.toString(constants);
}
return target.toString(constants) + hilight("." + Action.propertyNames[propertyIndex] + "=") + value.toString(constants);
return target.toString(constants) + hilight("." + Action.propertyNames[propertyIndex] + " = ") + value.toString(constants);
}
@Override

View File

@@ -67,7 +67,7 @@ public class SetVariableActionItem extends ActionItem implements SetTypeActionIt
@Override
public String toString(ConstantPool constants) {
if (name instanceof DirectValueActionItem || name instanceof GetVariableActionItem) {
return stripQuotes(name, constants) + hilight("=") + value.toString(constants);
return stripQuotes(name, constants) + hilight(" = ") + value.toString(constants);
} else {
return hilight("set(") + name.toString(constants) + hilight(",") + value.toString(constants) + hilight(")");
}

View File

@@ -65,7 +65,7 @@ public class StoreRegisterActionItem extends ActionItem implements SetTypeAction
@Override
public String toString(ConstantPool constants) {
return (define ? hilight("var ") : "") + hilight(register.translate() + "=") + value.toString(constants);
return (define ? hilight("var ") : "") + hilight(register.translate() + " = ") + value.toString(constants);
}
@Override

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, 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 General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.action.model;
import com.jpexs.decompiler.graph.GraphSourceItemPos;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.List;
/**
*
* @author JPEXS
*/
public class TemporaryRegister extends GraphTargetItem {
public TemporaryRegister(GraphTargetItem value) {
super(value.src, value.precedence);
this.value = value;
}
@Override
public String toString(List<Object> localData) {
return value.toString(localData);
}
@Override
public boolean hasReturnValue() {
return value.hasReturnValue();
}
@Override
public Object getResult() {
return value.getResult();
}
@Override
public List<GraphTargetItem> getAllSubItems() {
return value.getAllSubItems();
}
@Override
public List<GraphSourceItemPos> getNeededSources() {
return value.getNeededSources();
}
@Override
public GraphTargetItem getNotCoerced() {
return value.getNotCoerced();
}
}

View File

@@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
import com.jpexs.decompiler.flash.action.model.TemporaryRegister;
import com.jpexs.decompiler.flash.action.parser.ParseException;
import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol;
import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer;
@@ -347,13 +348,18 @@ public class ActionPush extends Action {
}
}*/
DirectValueActionItem dvt = new DirectValueActionItem(this, pos, o, constantPool);
stack.push(dvt);
if (o instanceof RegisterNumber) {
if (o instanceof RegisterNumber) {//TemporaryRegister
dvt.computedRegValue = variables.get("__register" + ((RegisterNumber) o).number);
if (regNames.containsKey(((RegisterNumber) o).number)) {
((RegisterNumber) o).name = regNames.get(((RegisterNumber) o).number);
}
}
if (dvt.computedRegValue instanceof TemporaryRegister) {
stack.push(((TemporaryRegister) dvt.computedRegValue).value);
} else {
stack.push(dvt);
}
pos++;
}
}

View File

@@ -19,11 +19,15 @@ package com.jpexs.decompiler.flash.action.swf4;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.model.DecrementActionItem;
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
import com.jpexs.decompiler.flash.action.model.GetPropertyActionItem;
import com.jpexs.decompiler.flash.action.model.IncrementActionItem;
import com.jpexs.decompiler.flash.action.model.PostDecrementActionItem;
import com.jpexs.decompiler.flash.action.model.PostIncrementActionItem;
import com.jpexs.decompiler.flash.action.model.SetPropertyActionItem;
import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem;
import com.jpexs.decompiler.flash.action.model.TemporaryRegister;
import com.jpexs.decompiler.flash.action.model.operations.PreDecrementActionItem;
import com.jpexs.decompiler.flash.action.model.operations.PreIncrementActionItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
@@ -61,7 +65,7 @@ public class ActionSetProperty extends Action {
}
}
}
if (value instanceof DecrementActionItem) {
if (value.getThroughDuplicate() instanceof DecrementActionItem) {
GraphTargetItem obj = ((DecrementActionItem) value).object;
if (!stack.isEmpty()) {
if (stack.peek().valueEquals(obj)) {
@@ -71,9 +75,31 @@ public class ActionSetProperty extends Action {
}
}
}
GraphTargetItem ret = new SetPropertyActionItem(this, target, indexInt, value);
if (value instanceof StoreRegisterActionItem) {
((StoreRegisterActionItem) value).define = false;
StoreRegisterActionItem sr = (StoreRegisterActionItem) value;
if (sr.define) {
value = sr.getValue();
((SetPropertyActionItem) ret).setValue(value);
if (value instanceof IncrementActionItem) {
if (((IncrementActionItem) value).object instanceof GetPropertyActionItem) {
if (((GetPropertyActionItem) ((IncrementActionItem) value).object).valueEquals(((SetPropertyActionItem) ret).getObject())) {
ret = new PreIncrementActionItem(this, ((IncrementActionItem) value).object);
}
}
} else if (value instanceof DecrementActionItem) {
if (((DecrementActionItem) value).object instanceof GetPropertyActionItem) {
if (((GetPropertyActionItem) ((DecrementActionItem) value).object).valueEquals(((SetPropertyActionItem) ret).getObject())) {
ret = new PreDecrementActionItem(this, ((DecrementActionItem) value).object);
}
}
}
variables.put("__register" + sr.register.number, new TemporaryRegister(ret));
return;
}
}
output.add(new SetPropertyActionItem(this, target, indexInt, value));
output.add(ret);
}
}

View File

@@ -25,6 +25,9 @@ import com.jpexs.decompiler.flash.action.model.PostDecrementActionItem;
import com.jpexs.decompiler.flash.action.model.PostIncrementActionItem;
import com.jpexs.decompiler.flash.action.model.SetVariableActionItem;
import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem;
import com.jpexs.decompiler.flash.action.model.TemporaryRegister;
import com.jpexs.decompiler.flash.action.model.operations.PreDecrementActionItem;
import com.jpexs.decompiler.flash.action.model.operations.PreIncrementActionItem;
import com.jpexs.decompiler.flash.helpers.Highlighting;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
@@ -83,10 +86,34 @@ public class ActionSetVariable extends Action {
}
}
}
GraphTargetItem ret = new SetVariableActionItem(this, name, value);
if (value instanceof StoreRegisterActionItem) {
((StoreRegisterActionItem) value).define = false;
StoreRegisterActionItem sr = (StoreRegisterActionItem) value;
if (sr.define) {
value = sr.getValue();
((SetVariableActionItem) ret).setValue(value);
if (value instanceof IncrementActionItem) {
if (((IncrementActionItem) value).object instanceof GetVariableActionItem) {
if (((GetVariableActionItem) ((IncrementActionItem) value).object).name.valueEquals(name)) {
ret = new PreIncrementActionItem(this, ((IncrementActionItem) value).object);
}
}
} else if (value instanceof DecrementActionItem) {
if (((DecrementActionItem) value).object instanceof GetVariableActionItem) {
if (((GetVariableActionItem) ((DecrementActionItem) value).object).name.valueEquals(name)) {
ret = new PreDecrementActionItem(this, ((DecrementActionItem) value).object);
}
}
}
variables.put("__register" + sr.register.number, new TemporaryRegister(ret));
return;
}
}
SetVariableActionItem svt = new SetVariableActionItem(this, name, value);
output.add(svt);
output.add(ret);
}
}

View File

@@ -24,6 +24,9 @@ import com.jpexs.decompiler.flash.action.model.PostDecrementActionItem;
import com.jpexs.decompiler.flash.action.model.PostIncrementActionItem;
import com.jpexs.decompiler.flash.action.model.SetMemberActionItem;
import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem;
import com.jpexs.decompiler.flash.action.model.TemporaryRegister;
import com.jpexs.decompiler.flash.action.model.operations.PreDecrementActionItem;
import com.jpexs.decompiler.flash.action.model.operations.PreIncrementActionItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
@@ -86,9 +89,29 @@ public class ActionSetMember extends Action {
}
}
}
GraphTargetItem ret = new SetMemberActionItem(this, object, memberName, value);
if (value instanceof StoreRegisterActionItem) {
((StoreRegisterActionItem) value).define = false;
StoreRegisterActionItem sr = (StoreRegisterActionItem) value;
if (sr.define) {
value = sr.getValue();
((SetMemberActionItem) ret).setValue(value);
if (value instanceof IncrementActionItem) {
if (((IncrementActionItem) value).object instanceof GetMemberActionItem) {
if (((GetMemberActionItem) ((IncrementActionItem) value).object).valueEquals(((SetMemberActionItem) ret).getObject())) {
ret = new PreIncrementActionItem(this, ((IncrementActionItem) value).object);
}
}
} else if (value instanceof DecrementActionItem) {
if (((DecrementActionItem) value).object instanceof GetMemberActionItem) {
if (((GetMemberActionItem) ((DecrementActionItem) value).object).valueEquals(((SetMemberActionItem) ret).getObject())) {
ret = new PreDecrementActionItem(this, ((DecrementActionItem) value).object);
}
}
}
variables.put("__register" + sr.register.number, new TemporaryRegister(ret));
return;
}
}
output.add(new SetMemberActionItem(this, object, memberName, value));
output.add(ret);
}
}

View File

@@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.action.model.IncrementActionItem;
import com.jpexs.decompiler.flash.action.model.PostDecrementActionItem;
import com.jpexs.decompiler.flash.action.model.PostIncrementActionItem;
import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem;
import com.jpexs.decompiler.flash.action.model.TemporaryRegister;
import com.jpexs.decompiler.flash.action.parser.ParseException;
import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer;
import com.jpexs.decompiler.flash.action.swf4.RegisterNumber;
@@ -80,6 +81,11 @@ public class ActionStoreRegister extends Action {
rn.name = regNames.get(registerNumber);
}
value.moreSrc.add(new GraphSourceItemPos(this, 0));
if (variables.containsKey("__register" + registerNumber)) {
if (variables.get("__register" + registerNumber) instanceof TemporaryRegister) {
variables.remove("__register" + registerNumber);
}
}
boolean define = !variables.containsKey("__register" + registerNumber);
if (regNames.containsKey(registerNumber)) {
define = false;

View File

@@ -578,7 +578,7 @@ public class Graph {
List<GraphTargetItem> ret = printGraph(new ArrayList<GraphPart>(), localData, stack, allParts, null, heads.get(0), null, loops, staticOperation, path);
processIfs(ret);
finalProcessStack(stack, ret);
finalProcessAll(ret, 0);
finalProcessAll(ret, 0, new ArrayList<>());
return ret;
@@ -587,19 +587,19 @@ public class Graph {
public void finalProcessStack(Stack<GraphTargetItem> stack, List<GraphTargetItem> output) {
}
private void finalProcessAll(List<GraphTargetItem> list, int level) {
finalProcess(list, level);
private void finalProcessAll(List<GraphTargetItem> list, int level, List<Object> localData) {
finalProcess(list, level, localData);
for (GraphTargetItem item : list) {
if (item instanceof Block) {
List<List<GraphTargetItem>> subs = ((Block) item).getSubs();
for (List<GraphTargetItem> sub : subs) {
finalProcessAll(sub, level + 1);
finalProcessAll(sub, level + 1, localData);
}
}
}
}
protected void finalProcess(List<GraphTargetItem> list, int level) {
protected void finalProcess(List<GraphTargetItem> list, int level, List<Object> localData) {
}
private void processIfs(List<GraphTargetItem> list) {