private List<Instruction> transformSetterInvocation(InvokeInstruction insn, String property) { ValueType type = insn.getMethod().getDescriptor().parameterType(0); List<Instruction> instructions = new ArrayList<>(); if (type instanceof ValueType.Primitive) { switch (((ValueType.Primitive) type).getKind()) { case BOOLEAN: castAndSetProperty(insn, property, instructions, boolean.class); return instructions; case BYTE: castAndSetProperty(insn, property, instructions, byte.class); return instructions; case SHORT: castAndSetProperty(insn, property, instructions, short.class); return instructions; case INTEGER: castAndSetProperty(insn, property, instructions, int.class); return instructions; case FLOAT: castAndSetProperty(insn, property, instructions, float.class); return instructions; case DOUBLE: castAndSetProperty(insn, property, instructions, double.class); return instructions; case CHARACTER: case LONG: break; } } else if (type instanceof ValueType.Object) { switch (((ValueType.Object) type).getClassName()) { case "java.lang.String": { Variable castVar = insn.getProgram().createVariable(); InvokeInstruction castInvoke = new InvokeInstruction(); castInvoke.setType(InvocationType.SPECIAL); castInvoke.setMethod( new MethodReference( ResourceAccessor.class, "castFromString", String.class, Object.class)); castInvoke.getArguments().add(insn.getArguments().get(0)); castInvoke.setReceiver(castVar); instructions.add(castInvoke); setProperty(insn, property, instructions, castVar); return instructions; } default: { setProperty(insn, property, instructions, insn.getArguments().get(0)); return instructions; } } } return null; }
@Override public void visit(MonitorExitInstruction insn) { MonitorExitStatement stmt = new MonitorExitStatement(); stmt.setLocation(currentLocation); stmt.setObjectRef(Expr.var(insn.getObjectRef().getIndex())); statements.add(stmt); }
@Override public void visit(RaiseInstruction insn) { ThrowStatement stmt = new ThrowStatement(); stmt.setLocation(currentLocation); stmt.setException(Expr.var(insn.getException().getIndex())); statements.add(stmt); }
@Override public void visit(JumpInstruction insn) { Statement stmt = generateJumpStatement(insn.getTarget()); if (stmt != null) { statements.add(stmt); } }
@Override public void visit(InvokeInstruction insn) { Expr[] exprArgs = new Expr[insn.getMethod().getParameterTypes().length]; for (int i = 0; i < insn.getArguments().size(); ++i) { exprArgs[i] = Expr.var(insn.getArguments().get(i).getIndex()); } InvocationExpr invocationExpr; if (insn.getInstance() != null) { if (insn.getType() == InvocationType.VIRTUAL) { invocationExpr = Expr.invoke(insn.getMethod(), Expr.var(insn.getInstance().getIndex()), exprArgs); } else { invocationExpr = Expr.invokeSpecial(insn.getMethod(), Expr.var(insn.getInstance().getIndex()), exprArgs); } } else { invocationExpr = Expr.invokeStatic(insn.getMethod(), exprArgs); } AssignmentStatement stmt; if (insn.getReceiver() != null) { stmt = Statement.assign(Expr.var(insn.getReceiver().getIndex()), invocationExpr); stmt.getDebugNames().addAll(insn.getReceiver().getDebugNames()); } else { stmt = Statement.assign(null, invocationExpr); } stmt.setLocation(currentLocation); stmt.setAsync(async); async = false; statements.add(stmt); }
@Override public void visit(GetFieldInstruction insn) { if (insn.getInstance() != null) { AssignmentStatement stmt = Statement.assign( Expr.var(insn.getReceiver().getIndex()), Expr.qualify(Expr.var(insn.getInstance().getIndex()), insn.getField())); stmt.setLocation(currentLocation); statements.add(stmt); } else { Expr fieldExpr = Expr.qualify(null, insn.getField()); AssignmentStatement stmt = Statement.assign(Expr.var(insn.getReceiver().getIndex()), fieldExpr); stmt.setLocation(currentLocation); statements.add(stmt); } }
@Override public void visit(ExitInstruction insn) { ReturnStatement stmt = Statement.exitFunction( insn.getValueToReturn() != null ? Expr.var(insn.getValueToReturn().getIndex()) : null); stmt.setLocation(currentLocation); statements.add(stmt); }
private void setProperty( InvokeInstruction insn, String property, List<Instruction> instructions, Variable valueVar) { Variable nameVar = program.createVariable(); StringConstantInstruction nameInsn = new StringConstantInstruction(); nameInsn.setConstant(property); nameInsn.setReceiver(nameVar); instructions.add(nameInsn); InvokeInstruction accessorInvoke = new InvokeInstruction(); accessorInvoke.setType(InvocationType.SPECIAL); accessorInvoke.setMethod( new MethodReference( ResourceAccessor.class, "put", Object.class, String.class, Object.class, void.class)); accessorInvoke.getArguments().add(insn.getInstance()); accessorInvoke.getArguments().add(nameVar); accessorInvoke.getArguments().add(valueVar); instructions.add(accessorInvoke); }
@Override public void visit(AssignInstruction insn) { AssignmentStatement stmt = Statement.assign( Expr.var(insn.getReceiver().getIndex()), Expr.var(insn.getAssignee().getIndex())); stmt.getDebugNames().addAll(insn.getReceiver().getDebugNames()); stmt.setLocation(currentLocation); statements.add(stmt); }
private void branch(Expr condition, BasicBlock consequentBlock, BasicBlock alternativeBlock) { Statement consequent = generateJumpStatement(consequentBlock); Statement alternative = generateJumpStatement(alternativeBlock); statements.add( Statement.cond( condition, consequent != null ? Arrays.asList(consequent) : Collections.emptyList(), alternative != null ? Arrays.asList(alternative) : Collections.emptyList())); }
@Override public void visit(PutElementInstruction insn) { AssignmentStatement stmt = Statement.assign( Expr.subscript( Expr.var(insn.getArray().getIndex()), Expr.var(insn.getIndex().getIndex())), Expr.var(insn.getValue().getIndex())); stmt.setLocation(currentLocation); statements.add(stmt); }
@Override public void visit(PutFieldInstruction insn) { Expr right = Expr.var(insn.getValue().getIndex()); Expr left; if (insn.getInstance() != null) { left = Expr.qualify(Expr.var(insn.getInstance().getIndex()), insn.getField()); } else { left = Expr.qualify(null, insn.getField()); } AssignmentStatement stmt = Statement.assign(left, right); stmt.setLocation(currentLocation); statements.add(stmt); }
private void castAndSetProperty( InvokeInstruction insn, String property, List<Instruction> instructions, Class<?> primitive) { Variable castVar = program.createVariable(); InvokeInstruction castInvoke = new InvokeInstruction(); castInvoke.setType(InvocationType.SPECIAL); String primitiveCapitalized = primitive.getName(); primitiveCapitalized = Character.toUpperCase(primitiveCapitalized.charAt(0)) + primitiveCapitalized.substring(1); castInvoke.setMethod( new MethodReference( ResourceAccessor.class, "castFrom" + primitiveCapitalized, primitive, Object.class)); castInvoke.getArguments().add(insn.getArguments().get(0)); castInvoke.setReceiver(castVar); instructions.add(castInvoke); setProperty(insn, property, instructions, castVar); }
private void transformBasicBlock(BasicBlock block) { List<Instruction> instructions = block.getInstructions(); for (int i = 0; i < instructions.size(); ++i) { Instruction insn = instructions.get(i); if (insn instanceof InvokeInstruction) { InvokeInstruction invoke = (InvokeInstruction) insn; List<Instruction> replacement = transformInvoke(invoke); if (replacement != null) { instructions.set(i, new EmptyInstruction()); instructions.addAll(i, replacement); i += replacement.size(); } } } }
@Override public void visit(SwitchInstruction insn) { SwitchStatement stmt = new SwitchStatement(); stmt.setId("sblock" + (lastSwitchId++)); stmt.setValue(Expr.var(insn.getCondition().getIndex())); Map<Integer, List<Integer>> switchMap = new HashMap<>(); for (int i = 0; i < insn.getEntries().size(); ++i) { SwitchTableEntry entry = insn.getEntries().get(i); List<Integer> conditions = switchMap.get(entry.getTarget().getIndex()); if (conditions == null) { conditions = new ArrayList<>(); switchMap.put(entry.getTarget().getIndex(), conditions); } conditions.add(entry.getCondition()); } List<Integer> targets = new ArrayList<>(switchMap.keySet()); Collections.sort(targets); for (int target : targets) { SwitchClause clause = new SwitchClause(); List<Integer> conditionList = switchMap.get(target); int[] conditions = new int[conditionList.size()]; for (int i = 0; i < conditionList.size(); ++i) { conditions[i] = conditionList.get(i); } clause.setConditions(conditions); Statement jumpStmt = generateJumpStatement(stmt, target); if (jumpStmt != null) { clause.getBody().add(jumpStmt); } stmt.getClauses().add(clause); } Statement breakStmt = generateJumpStatement(insn.getDefaultTarget()); if (breakStmt != null) { stmt.getDefaultClause().add(breakStmt); } statements.add(stmt); }
@Override public void visit(InitClassInstruction insn) { InitClassStatement stmt = Statement.initClass(insn.getClassName()); stmt.setLocation(currentLocation); statements.add(stmt); }
private void assign(Expr source, Variable target) { AssignmentStatement stmt = Statement.assign(Expr.var(target.getIndex()), source); stmt.setLocation(currentLocation); stmt.getDebugNames().addAll(target.getDebugNames()); statements.add(stmt); }