@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); }
private void getAndCastProperty( InvokeInstruction insn, String property, List<Instruction> instructions, Class<?> primitive) { Variable resultVar = program.createVariable(); getProperty(insn, property, instructions, resultVar); 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, "castTo" + primitiveCapitalized, Object.class, primitive)); castInvoke.getArguments().add(resultVar); castInvoke.setReceiver(insn.getReceiver()); instructions.add(castInvoke); }
private List<Instruction> transformInvoke(InvokeInstruction insn) { if (insn.getType() != InvocationType.VIRTUAL) { return null; } MethodReference method = insn.getMethod(); if (method.getClassName().equals(ResourceArray.class.getName()) || method.getClassName().equals(ResourceMap.class.getName())) { if (method.getName().equals("keys")) { return transformKeys(insn); } InvokeInstruction accessInsn = new InvokeInstruction(); accessInsn.setType(InvocationType.SPECIAL); ValueType[] types = new ValueType[method.getDescriptor().parameterCount() + 2]; types[0] = ValueType.object("java.lang.Object"); System.arraycopy( method.getDescriptor().getSignature(), 0, types, 1, method.getDescriptor().parameterCount() + 1); accessInsn.setMethod( new MethodReference(ResourceAccessor.class.getName(), method.getName(), types)); accessInsn.getArguments().add(insn.getInstance()); accessInsn.getArguments().addAll(insn.getArguments()); accessInsn.setReceiver(insn.getReceiver()); return Arrays.asList(accessInsn); } ClassReader iface = innerSource.get(method.getClassName()); if (iface == null || !innerSource.isSuperType(Resource.class.getName(), iface.getName()).orElse(false)) { return null; } if (method.getName().startsWith("get")) { if (method.getName().length() > 3) { return transformGetterInvocation(insn, getPropertyName(method.getName().substring(3))); } } else if (method.getName().startsWith("is")) { if (method.getName().length() > 2) { return transformGetterInvocation(insn, getPropertyName(method.getName().substring(2))); } } else if (method.getName().startsWith("set")) { if (method.getName().length() > 3) { return transformSetterInvocation(insn, getPropertyName(method.getName().substring(3))); } } return null; }
private List<Instruction> transformKeys(InvokeInstruction insn) { Variable tmp = program.createVariable(); InvokeInstruction keysInsn = new InvokeInstruction(); keysInsn.setType(InvocationType.SPECIAL); keysInsn.setMethod( new MethodReference(ResourceAccessor.class, "keys", Object.class, Object.class)); keysInsn.getArguments().add(insn.getInstance()); keysInsn.setReceiver(tmp); InvokeInstruction transformInsn = new InvokeInstruction(); transformInsn.setType(InvocationType.SPECIAL); transformInsn.setMethod( new MethodReference(ResourceAccessor.class, "keysToStrings", Object.class, String[].class)); transformInsn.getArguments().add(tmp); transformInsn.setReceiver(insn.getReceiver()); return Arrays.asList(keysInsn, transformInsn); }
private List<Instruction> transformGetterInvocation(InvokeInstruction insn, String property) { if (insn.getReceiver() == null) { return Collections.emptyList(); } ValueType type = insn.getMethod().getDescriptor().getResultType(); List<Instruction> instructions = new ArrayList<>(); if (type instanceof ValueType.Primitive) { switch (((ValueType.Primitive) type).getKind()) { case BOOLEAN: getAndCastProperty(insn, property, instructions, boolean.class); return instructions; case BYTE: getAndCastProperty(insn, property, instructions, byte.class); return instructions; case SHORT: getAndCastProperty(insn, property, instructions, short.class); return instructions; case INTEGER: getAndCastProperty(insn, property, instructions, int.class); return instructions; case FLOAT: getAndCastProperty(insn, property, instructions, float.class); return instructions; case DOUBLE: getAndCastProperty(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 resultVar = insn.getProgram().createVariable(); getProperty(insn, property, instructions, resultVar); InvokeInstruction castInvoke = new InvokeInstruction(); castInvoke.setType(InvocationType.SPECIAL); castInvoke.setMethod( new MethodReference( ResourceAccessor.class, "castToString", Object.class, String.class)); castInvoke.getArguments().add(resultVar); castInvoke.setReceiver(insn.getReceiver()); instructions.add(castInvoke); return instructions; } default: { Variable resultVar = insn.getProgram().createVariable(); getProperty(insn, property, instructions, resultVar); CastInstruction castInsn = new CastInstruction(); castInsn.setReceiver(insn.getReceiver()); castInsn.setTargetType(type); castInsn.setValue(resultVar); instructions.add(castInsn); return instructions; } } } return null; }