Search in sources :

Example 1 with NullPermeableHashMap

use of org.mapleir.stdlib.collections.map.NullPermeableHashMap in project maple-ir by LLVM-but-worse.

the class SSAGenPass method splitRanges.

private void splitRanges() {
    // produce cleaner cfg
    List<BasicBlock> order = new ArrayList<>(builder.graph.vertices());
    NullPermeableHashMap<BasicBlock, Set<Local>> splits = new NullPermeableHashMap<>(SetCreator.getInstance());
    for (ExceptionRange<BasicBlock> er : builder.graph.getRanges()) {
        BasicBlock h = er.getHandler();
        handlers.add(h);
        Set<Local> ls = new HashSet<>(liveness.in(h));
        for (BasicBlock b : er.get()) {
            splits.getNonNull(b).addAll(ls);
        }
    }
    for (Entry<BasicBlock, Set<Local>> e : splits.entrySet()) {
        BasicBlock b = e.getKey();
        Set<Local> ls = e.getValue();
        ArrayList<Stmt> stmtsCopy = new ArrayList<>(b);
        int i = 0;
        boolean checkSplit = false;
        for (int i1 = 0; i1 < stmtsCopy.size(); i1++) {
            Stmt stmt = stmtsCopy.get(i1);
            if (b.size() == i)
                throw new IllegalStateException("s");
            if (checkSplit && stmt.getOpcode() == Opcode.LOCAL_STORE) {
                CopyVarStmt copy = (CopyVarStmt) stmt;
                VarExpr v = copy.getVariable();
                if (ls.contains(v.getLocal())) {
                    BasicBlock n = splitBlock(b, i);
                    order.add(order.indexOf(b), n);
                    i = 0;
                    checkSplit = false;
                }
            } else {
                // do not split if we have only seen simple or synthetic copies (catch copy is synthetic)
                if (stmt instanceof CopyVarStmt) {
                    CopyVarStmt copy = (CopyVarStmt) stmt;
                    int opc = copy.getExpression().getOpcode();
                    if (!copy.isSynthetic() && opc != Opcode.LOCAL_LOAD && opc != Opcode.CATCH) {
                        checkSplit = true;
                    }
                } else {
                    checkSplit = true;
                }
            }
            i++;
        }
    }
    builder.graph.naturalise(order);
    int po = 0;
    for (BasicBlock b : SimpleDfs.preorder(builder.graph, builder.graph.getEntries().iterator().next())) {
        insertion.put(b, 0);
        process.put(b, 0);
        preorder.put(b, po++);
    }
}
Also used : CopyVarStmt(org.mapleir.ir.code.stmt.copy.CopyVarStmt) BasicBlock(org.mapleir.ir.cfg.BasicBlock) BasicLocal(org.mapleir.ir.locals.impl.BasicLocal) Local(org.mapleir.ir.locals.Local) VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) Constraint(org.mapleir.ir.cfg.builder.ssaopt.Constraint) SwitchStmt(org.mapleir.ir.code.stmt.SwitchStmt) CopyVarStmt(org.mapleir.ir.code.stmt.copy.CopyVarStmt) PopStmt(org.mapleir.ir.code.stmt.PopStmt) ThrowStmt(org.mapleir.ir.code.stmt.ThrowStmt) UnconditionalJumpStmt(org.mapleir.ir.code.stmt.UnconditionalJumpStmt) Stmt(org.mapleir.ir.code.Stmt) CopyPhiStmt(org.mapleir.ir.code.stmt.copy.CopyPhiStmt) ConditionalJumpStmt(org.mapleir.ir.code.stmt.ConditionalJumpStmt) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) NullPermeableHashMap(org.mapleir.stdlib.collections.map.NullPermeableHashMap) VarExpr(org.mapleir.ir.code.expr.VarExpr)

Example 2 with NullPermeableHashMap

use of org.mapleir.stdlib.collections.map.NullPermeableHashMap in project maple-ir by LLVM-but-worse.

the class DefaultInvocationResolver method computeVTable.

private void computeVTable(ClassNode c) {
    if (c == null) {
        throw new NullPointerException();
    }
    /* only visit each class once */
    if (hasVisited(c)) {
        return;
    }
    /* ensure parents loaded */
    ClassNode superKlass = null;
    /* if the super class is null it means we're at object and so
		 * we don't even have to consider interfaces: as we stop
		 * here */
    if (c.superName != null) {
        computeVTable(superKlass = app.findClassNode(c.superName));
        for (String i : c.interfaces) {
            computeVTable(app.findClassNode(i));
        }
    }
    /* the general plan of attack here is:
		 *  1. add our own methods.
		 *  2. merge without our super class methods.
		 *  3. merge and resolve with our interfaces. */
    /* we build our local tables for the current class. it's
		 * important to keep these separate from what will become the
		 * completely hierarchy sensitive lookup tables later and so
		 * technically should be immutable after the loop but we can
		 * ignore this as long as we do not modify them later. */
    Map<Selector, MethodNode> thisMethodSet = new HashMap<>();
    Map<Selector, MethodNode> thisAbstractSet = new HashMap<>();
    for (MethodNode m : c.methods) {
        /* we can easily resolve these as they come
			 * so we don't even need them in the table. */
        if (Modifier.isStatic(m.access)) {
            continue;
        }
        /* immutable lookup key */
        Selector s = new Selector(m.name, m.desc);
        /* store our local declarations. */
        if (Modifier.isAbstract(m.access)) {
            putOrThrow(thisAbstractSet, s, m);
        } else {
            putOrThrow(thisMethodSet, s, m);
        }
    }
    if (debugLevel >= 2) {
        LOGGER.debug("Class: " + c);
        LOGGER.debug("  super: " + c.superName);
        LOGGER.debug("  interfaces: " + c.interfaces.toString());
        LOGGER.debug(" implSet: ");
        print(thisMethodSet);
        LOGGER.debug(" absSet: ");
        print(thisAbstractSet);
    }
    /* Store the local results as the global as in the case of
		 * java/lang/Object we don't have a super class and so the
		 * ensuing analysis (below) is never executed. It's important
		 * to note that we shouldn't be looking in the global vtable
		 * for a given class while processing that class; the local
		 * maps/vtable values are used but not the field
		 * references. */
    concreteVTables.put(c, thisMethodSet);
    abstractVTables.put(c, thisAbstractSet);
    if (superKlass != null) {
        if (!hasVisited(superKlass)) {
            throw new IllegalStateException(String.format("Parent of %s, %s is not initialised", c, superKlass));
        }
        Map<Selector, MethodNode> globalCVT = new HashMap<>();
        Map<Selector, MethodNode> globalAVT = new HashMap<>();
        /* inherit all super class methods */
        globalCVT.putAll(concreteVTables.get(superKlass));
        globalAVT.putAll(abstractVTables.get(superKlass));
        assertIntersection(thisAbstractSet.entrySet(), thisMethodSet.entrySet(), Collections.emptySet());
        /* (1) and (2) 
			 * NOTE: thisAbstractSet and thisMethodSet should
			 *       intersect to give the null set. */
        for (Selector s : thisAbstractSet.keySet()) {
            globalCVT.remove(s);
        }
        for (Selector s : thisMethodSet.keySet()) {
            globalAVT.remove(s);
        }
        /* we shouldn't ever get merge errors from considering the
			 * current class with it's super. (this can happen with
			 * interfaces, however) */
        assertIntersection(globalAVT.entrySet(), globalCVT.entrySet(), Collections.emptySet());
        /* add our own declarations to the tables. this could possibly
			 * override methods from the super class and we're happy
			 * about this. */
        globalCVT.putAll(thisMethodSet);
        globalAVT.putAll(thisAbstractSet);
        assertIntersection(globalAVT.entrySet(), globalCVT.entrySet(), Collections.emptySet());
        concreteVTables.put(c, globalCVT);
        abstractVTables.put(c, globalAVT);
        if (debugLevel >= 3) {
            LOGGER.debug(" globalCVT: ");
            print(globalCVT);
            LOGGER.debug(" globalAVT: ");
            print(globalAVT);
        }
        NullPermeableHashMap<Selector, Set<MethodNode>> mergeMap = new NullPermeableHashMap<>(new SetCreator<>());
        if (debugLevel >= 2) {
            LOGGER.debug(" process interfaces:");
        }
        for (String i : c.interfaces) {
            if (debugLevel >= 2) {
                LOGGER.debug("  " + i);
            }
            ClassNode interfaceKlass = app.findClassNode(i);
            /* An abstract interface method cannot kill
				 * a concrete class implementation of the method
				 * from the super class. However, if the reaching
				 * definition is a default implementation from
				 * another interface which is a superclass of the
				 * current interface, then the reaching definition
				 * in the current interface is an abstract method
				 * and so that is propagated into the implementor.
				 * 
				 * If for example the super interface defines the
				 * abstract method and the sub interface has a
				 * default implementation and we implement the 
				 * default interface, the default method will become
				 * the reaching definition for the current class,
				 * not the abstract one.
				 * 
				 * If a class that implements a default method
				 * already has a reaching definition in the parent,
				 * the subinterface default method takes priority.*/
            add(concreteVTables.get(interfaceKlass), mergeMap);
            add(abstractVTables.get(interfaceKlass), mergeMap);
        }
        if (debugLevel >= 3) {
            LOGGER.debug("   mergeMap:");
            printMap(mergeMap);
        }
        for (Entry<Selector, Set<MethodNode>> e : mergeMap.entrySet()) {
            Selector selector = e.getKey();
            Set<MethodNode> conflictingMethods = e.getValue();
            MethodNode resolve;
            if (conflictingMethods.size() > 1) {
                if (debugLevel >= 2) {
                    LOGGER.debug("    conflicts: " + conflictingMethods.size());
                    LOGGER.debug("      " + selector);
                    for (MethodNode m : conflictingMethods) {
                        LOGGER.debug("      ^" + m);
                    }
                }
                /* if we have any sort of declaration, we can easily say that
					 * that is the target without having to check the hierarchy
					 * and globalCVT rules. 
					 * 
					 * 05/10/17: globalCVT should contain super defs as well or ours
					 *           so surely we use this as it doesn't contain any
					 *           abstracts?*/
                if (globalCVT.containsKey(selector)) {
                    resolve = globalCVT.get(selector);
                    if (debugLevel >= 2) {
                        LOGGER.debug("    (1)resolved to " + resolve);
                    }
                } else if (thisAbstractSet.containsKey(selector)) {
                    resolve = thisAbstractSet.get(selector);
                    if (debugLevel >= 2) {
                        LOGGER.debug("    (2)resolved to " + resolve);
                    }
                } else {
                    /* here is where it gets tricky. */
                    /* 05/10/17: weird bug? example:
						 *    javax/swing/LayoutComparator implements Comparable
						 *    Comparable extends Object by OUR own definition.
						 *    Comparable reabstracts equals(Object) but LayoutComparator
						 *    extends Object implicitly, so the Object definition is
						 *    reaching unless it is redefined in LayoutComparator.
						 *    Note that you can't have default methods for Object methods.
						 *    
						 *    So do we check for it here or inherit Objects methods before we
						 *    do anything else?
						 *    solution: use global vtable merge interface merges above?
						 */
                    Collection<MethodNode> contenders = getMaximallySpecific(conflictingMethods);
                    if (contenders.isEmpty()) {
                        throw new IllegalStateException();
                    }
                    if (contenders.size() == 1) {
                        /* design decision: if there is only 1 contender but multiple
							 * conflicting methods, all of the conflicting methods are
							 * defaults, then we have a clear target method, but if any of
							 * them are abstract, we are actually propagating a
							 * reabstraction through this class, so we can insert a
							 * miranda. */
                        boolean anyAbstract = false;
                        for (MethodNode m : contenders) {
                            anyAbstract |= Modifier.isAbstract(m.access);
                        }
                        if (anyAbstract) {
                            /* valid: miranda (reabstraction) */
                            resolve = null;
                        } else {
                            resolve = contenders.iterator().next();
                        }
                        if (debugLevel >= 2) {
                            LOGGER.debug("    (3)resolved to " + resolve);
                        }
                    } else {
                        if (c.isAbstract()) {
                            boolean allAbstract = true;
                            for (MethodNode m : contenders) {
                                allAbstract &= Modifier.isAbstract(m.access);
                            }
                            if (allAbstract) {
                                /* valid: miranda */
                                resolve = null;
                            } else {
                                /* require a declaration but we don't
									 * have one -> die. */
                                throw new IllegalStateException(String.format("Method %s is ambiguous in %s, candidates:%s", selector, c, conflictingMethods));
                            }
                        } else {
                            /* require a declaration but we don't
								 * have one -> die. */
                            throw new IllegalStateException(String.format("Method %s is ambiguous in %s, candidates:%s", selector, c, conflictingMethods));
                        }
                    }
                }
            } else {
                /* no conflicts, so we can just choose the resolve method as
					 * the target method from one of the tables. */
                if (globalCVT.containsKey(selector)) {
                    resolve = globalCVT.get(selector);
                } else if (thisAbstractSet.containsKey(selector)) {
                    /* thisAbstractSet instead of the global one because
						 * these conflicts would make things confusing if
						 * the global table was constantly changing. */
                    resolve = thisAbstractSet.get(selector);
                } else {
                    /* no conflict but the current class just does not implement
						 * the method itself. we could either create a miranda here or
						 * reference to method. we will do the latter. */
                    // size == 1
                    resolve = conflictingMethods.iterator().next();
                }
            }
            /* delete from both so we can do a clean add after. */
            globalAVT.remove(selector);
            globalCVT.remove(selector);
            if (resolve == null && !c.isAbstract()) {
                throw new IllegalStateException(String.format("Miranda %s in non abstract class %s", conflictingMethods, c));
            }
            if (resolve == null) {
                // TODO: sigs?
                resolve = new MethodNode(c, Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, selector.name, selector.desc, null, getExceptionClasses(conflictingMethods));
                c.methods.add(resolve);
                if (debugLevel >= 2) {
                    LOGGER.debug("  generated miranda " + resolve);
                }
            }
            if (Modifier.isAbstract(resolve.access)) {
                globalAVT.put(selector, resolve);
            } else {
                globalCVT.put(selector, resolve);
            }
        }
        assertIntersection(concreteVTables.get(c).entrySet(), abstractVTables.get(c).entrySet(), Collections.emptySet());
        if (debugLevel >= 2) {
            LOGGER.debug(" cvtable: ");
            print(concreteVTables.get(c));
            LOGGER.debug(" avtable: ");
            print(abstractVTables.get(c));
        }
    }
}
Also used : ClassNode(org.objectweb.asm.tree.ClassNode) NullPermeableHashMap(org.mapleir.stdlib.collections.map.NullPermeableHashMap) MethodNode(org.objectweb.asm.tree.MethodNode) NullPermeableHashMap(org.mapleir.stdlib.collections.map.NullPermeableHashMap)

Example 3 with NullPermeableHashMap

use of org.mapleir.stdlib.collections.map.NullPermeableHashMap in project maple-ir by LLVM-but-worse.

the class LocalsPool method realloc.

/* public Local newLocal(boolean isStack) {
		int index = cache.size();
		while(true) {
			String key = key(index, isStack);
			if(!cache.containsKey(key)) {
				return get(index, isStack);
			}
		}
	} */
public int realloc(ControlFlowGraph cfg) {
    NullPermeableHashMap<Local, Set<Type>> types = new NullPermeableHashMap<>(SetCreator.getInstance());
    int min = 0;
    Set<Local> safe = new HashSet<>();
    for (BasicBlock b : cfg.vertices()) {
        for (Stmt stmt : b) {
            if (stmt.getOpcode() == Opcode.LOCAL_STORE) {
                CopyVarStmt cp = (CopyVarStmt) stmt;
                VarExpr var = cp.getVariable();
                Local local = var.getLocal();
                if (!cp.isSynthetic()) {
                    types.getNonNull(local).add(var.getType());
                } else {
                    safe.add(local);
                }
                types.getNonNull(local).add(var.getType());
            }
            for (Expr s : stmt.enumerateOnlyChildren()) {
                if (s.getOpcode() == Opcode.LOCAL_LOAD) {
                    VarExpr var = (VarExpr) s;
                    Local local = var.getLocal();
                    types.getNonNull(local).add(var.getType());
                }
            }
        }
    }
    Map<Local, Type> stypes = new HashMap<>();
    for (Entry<Local, Set<Type>> e : types.entrySet()) {
        Set<Type> set = e.getValue();
        Set<Type> refined = new HashSet<>();
        if (set.size() > 1) {
            for (Type t : set) {
                refined.add(TypeUtils.asSimpleType(t));
            }
            if (refined.size() != 1) {
                boolean valid = false;
                if (refined.size() == 2) {
                    // TODO: proper check
                    Iterator<Type> it = refined.iterator();
                    if (it.next().getSize() == it.next().getSize()) {
                        Type t = refined.iterator().next();
                        refined.clear();
                        refined.add(t);
                        valid = true;
                    }
                }
                if (!valid) {
                    for (Entry<Local, Set<Type>> e1 : types.entrySet()) {
                        System.err.println(e1.getKey() + "  ==  " + e1.getValue());
                    }
                    // String.format("illegal typesets for %s, set=%s, refined=%s", args)
                    throw new RuntimeException("illegal typesets for " + e.getKey());
                }
            }
            Local l = e.getKey();
            stypes.put(l, refined.iterator().next());
        // if(!safe.contains(l)) {
        // stypes.put(l, refined.iterator().next());
        // }
        } else {
            Local l = e.getKey();
            stypes.put(l, set.iterator().next());
        // if(!safe.contains(l)) {
        // }
        }
    }
    // for(Entry<Local, Type> e : stypes.entrySet()) {
    // System.out.println(e.getKey() + "  ==  " + e.getValue());
    // }
    // lvars then svars, ordered of course,
    List<Local> wl = new ArrayList<>(stypes.keySet());
    // System.out.println("safe: " + safe);
    wl.sort(new Comparator<Local>() {

        @Override
        public int compare(Local o1, Local o2) {
            boolean s1 = safe.contains(o1);
            boolean s2 = safe.contains(o2);
            if (s1 && !s2) {
                return -1;
            } else if (!s1 && s2) {
                return 1;
            } else {
                return o1.compareTo(o2);
            }
        }
    });
    // System.out.println("wl: " + wl);
    Map<Local, Local> remap = new HashMap<>();
    int idx = min;
    for (Local l : wl) {
        Type type = stypes.get(l);
        Local newL = get(idx, false);
        if (l != newL) {
            remap.put(l, newL);
        }
        idx += type.getSize();
    }
    remap(cfg, remap);
    return idx;
}
Also used : GenericBitSet(org.mapleir.stdlib.collections.bitset.GenericBitSet) NullPermeableHashMap(org.mapleir.stdlib.collections.map.NullPermeableHashMap) Stmt(org.mapleir.ir.code.Stmt) CopyVarStmt(org.mapleir.ir.code.stmt.copy.CopyVarStmt) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) NullPermeableHashMap(org.mapleir.stdlib.collections.map.NullPermeableHashMap) VarExpr(org.mapleir.ir.code.expr.VarExpr) CopyVarStmt(org.mapleir.ir.code.stmt.copy.CopyVarStmt) BasicBlock(org.mapleir.ir.cfg.BasicBlock) VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) BasicLocal(org.mapleir.ir.locals.impl.BasicLocal) Type(org.objectweb.asm.Type) VarExpr(org.mapleir.ir.code.expr.VarExpr) Expr(org.mapleir.ir.code.Expr)

Example 4 with NullPermeableHashMap

use of org.mapleir.stdlib.collections.map.NullPermeableHashMap in project maple-ir by LLVM-but-worse.

the class BoissinotDestructor method copyPhiOperands.

private void copyPhiOperands(BasicBlock b) {
    NullPermeableHashMap<BasicBlock, List<PhiRes>> wl = new NullPermeableHashMap<>(new ListCreator<>());
    ParallelCopyVarStmt dst_copy = new ParallelCopyVarStmt();
    for (Stmt stmt : b) {
        // phis only appear at the start of a block.
        if (stmt.getOpcode() != Opcode.PHI_STORE) {
            break;
        }
        CopyPhiStmt copy = (CopyPhiStmt) stmt;
        PhiExpr phi = copy.getExpression();
        // so that we can parallelise the copy when we insert it.
        for (Entry<BasicBlock, Expr> e : phi.getArguments().entrySet()) {
            BasicBlock h = e.getKey();
            // these are validated in init().
            VarExpr v = (VarExpr) e.getValue();
            PhiRes r = new PhiRes(copy.getVariable().getLocal(), phi, h, v.getLocal(), v.getType());
            wl.getNonNull(h).add(r);
        }
        // for each x0, where x0 is a phi copy target, create a new variable z0 for
        // a copy x0 = z0 and replace the phi copy target to z0.
        Local x0 = copy.getVariable().getLocal();
        Local z0 = locals.makeLatestVersion(x0);
        // x0 = z0
        dst_copy.pairs.add(new CopyPair(x0, z0, copy.getVariable().getType()));
        // z0 = phi(...)
        copy.getVariable().setLocal(z0);
    }
    // resolve
    if (dst_copy.pairs.size() > 0)
        insertStart(b, dst_copy);
    for (Entry<BasicBlock, List<PhiRes>> e : wl.entrySet()) {
        BasicBlock p = e.getKey();
        ParallelCopyVarStmt copy = new ParallelCopyVarStmt();
        for (PhiRes r : e.getValue()) {
            // for each xi source in a phi, create a new variable zi, and insert the copy
            // zi = xi in the pred Li. then replace the phi arg from Li with zi.
            Local xi = r.l;
            Local zi = locals.makeLatestVersion(xi);
            copy.pairs.add(new CopyPair(zi, xi, r.type));
            // we consider phi args to be used in the pred instead of the block
            // where the phi is, so we need to update the def/use maps here.
            r.phi.setArgument(r.pred, new VarExpr(zi, r.type));
        }
        insertEnd(p, copy);
    }
}
Also used : BasicBlock(org.mapleir.ir.cfg.BasicBlock) Local(org.mapleir.ir.locals.Local) VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) CopyVarStmt(org.mapleir.ir.code.stmt.copy.CopyVarStmt) Stmt(org.mapleir.ir.code.Stmt) CopyPhiStmt(org.mapleir.ir.code.stmt.copy.CopyPhiStmt) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) CopyPhiStmt(org.mapleir.ir.code.stmt.copy.CopyPhiStmt) VarExpr(org.mapleir.ir.code.expr.VarExpr) Expr(org.mapleir.ir.code.Expr) PhiExpr(org.mapleir.ir.code.expr.PhiExpr) NullPermeableHashMap(org.mapleir.stdlib.collections.map.NullPermeableHashMap) PhiExpr(org.mapleir.ir.code.expr.PhiExpr) VarExpr(org.mapleir.ir.code.expr.VarExpr)

Example 5 with NullPermeableHashMap

use of org.mapleir.stdlib.collections.map.NullPermeableHashMap in project maple-ir by LLVM-but-worse.

the class DefUseVerifier method verify0.

public static void verify0(ControlFlowGraph cfg) {
    LocalsPool lp = cfg.getLocals();
    Map<Local, AbstractCopyStmt> defs = new HashMap<>();
    NullPermeableHashMap<VersionedLocal, Set<VarExpr>> uses = new NullPermeableHashMap<>(SetCreator.getInstance());
    for (BasicBlock b : cfg.vertices()) {
        for (Stmt stmt : b) {
            if (stmt.getOpcode() == Opcode.LOCAL_STORE || stmt.getOpcode() == Opcode.PHI_STORE) {
                AbstractCopyStmt copy = (AbstractCopyStmt) stmt;
                defs.put(copy.getVariable().getLocal(), copy);
            }
            for (Expr e : stmt.enumerateOnlyChildren()) {
                if (e.getOpcode() == Opcode.LOCAL_LOAD) {
                    VarExpr v = (VarExpr) e;
                    uses.getNonNull((VersionedLocal) v.getLocal()).add(v);
                }
            }
        }
    }
    {
        Set<Local> dlocals = new HashSet<>();
        dlocals.addAll(defs.keySet());
        dlocals.addAll(lp.defs.keySet());
        for (Local l : dlocals) {
            if (!defs.containsKey(l)) {
                throw new IllegalStateException("(other): def of " + l);
            }
            if (!lp.defs.containsKey(l)) {
                throw new IllegalStateException("(real): def of " + l);
            }
            AbstractCopyStmt copy1 = defs.get(l);
            AbstractCopyStmt copy2 = lp.defs.get(l);
            if (copy1 != copy2) {
                throw new IllegalStateException("dtest: " + copy1 + " :: " + copy2);
            }
        }
    }
    {
        Set<VersionedLocal> ulocals = new HashSet<>();
        ulocals.addAll(uses.keySet());
        ulocals.addAll(lp.uses.keySet());
        for (VersionedLocal l : ulocals) {
            /*if(!uses.containsKey(l)) {
					throw new IllegalStateException("(other): use of " + l);
				}
				
				if(!lp.uses.containsKey(l)) {
					throw new IllegalStateException("(real): use of " + l);
				}*/
            Set<VarExpr> uses1 = uses.get(l);
            Set<VarExpr> uses2 = lp.uses.get(l);
            if (uses1 == null) {
                if (uses2.size() != 0) {
                    throw new IllegalStateException(String.format("utest1: %s, u1:null :: u2:%d", l, uses2.size()));
                }
            } else if (uses2 == null) {
                if (uses1.size() == 0) {
                    throw new IllegalStateException(String.format("utest2: %s, u1:%d :: u2:null", l, uses1.size()));
                }
            } else {
                if (uses2.size() != uses1.size()) {
                    throw new IllegalStateException(String.format("utest3: %s, u1:%d :: u2:%d", l, uses1.size(), uses2.size()));
                }
            }
        }
    }
}
Also used : VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) Set(java.util.Set) HashSet(java.util.HashSet) HashMap(java.util.HashMap) NullPermeableHashMap(org.mapleir.stdlib.collections.map.NullPermeableHashMap) BasicBlock(org.mapleir.ir.cfg.BasicBlock) Local(org.mapleir.ir.locals.Local) VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) Stmt(org.mapleir.ir.code.Stmt) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) LocalsPool(org.mapleir.ir.locals.LocalsPool) VarExpr(org.mapleir.ir.code.expr.VarExpr) Expr(org.mapleir.ir.code.Expr) NullPermeableHashMap(org.mapleir.stdlib.collections.map.NullPermeableHashMap) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) VarExpr(org.mapleir.ir.code.expr.VarExpr)

Aggregations

NullPermeableHashMap (org.mapleir.stdlib.collections.map.NullPermeableHashMap)5 BasicBlock (org.mapleir.ir.cfg.BasicBlock)4 Stmt (org.mapleir.ir.code.Stmt)4 VarExpr (org.mapleir.ir.code.expr.VarExpr)4 AbstractCopyStmt (org.mapleir.ir.code.stmt.copy.AbstractCopyStmt)4 VersionedLocal (org.mapleir.ir.locals.impl.VersionedLocal)4 Expr (org.mapleir.ir.code.Expr)3 CopyVarStmt (org.mapleir.ir.code.stmt.copy.CopyVarStmt)3 Local (org.mapleir.ir.locals.Local)3 CopyPhiStmt (org.mapleir.ir.code.stmt.copy.CopyPhiStmt)2 BasicLocal (org.mapleir.ir.locals.impl.BasicLocal)2 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Set (java.util.Set)1 Constraint (org.mapleir.ir.cfg.builder.ssaopt.Constraint)1 PhiExpr (org.mapleir.ir.code.expr.PhiExpr)1 ConditionalJumpStmt (org.mapleir.ir.code.stmt.ConditionalJumpStmt)1 PopStmt (org.mapleir.ir.code.stmt.PopStmt)1 SwitchStmt (org.mapleir.ir.code.stmt.SwitchStmt)1 ThrowStmt (org.mapleir.ir.code.stmt.ThrowStmt)1