DonateLiveCodeTransformation extends DonateCodeTransformation { @Override Stmt prepareStatementToDonate(IInjectionPoint injectionPoint, DonationContext donationContext, TransformationProbabilities probabilities, IRandom generator, ShadingLanguageVersion shadingLanguageVersion) { List<Stmt> donatedStmts = new ArrayList<>(); for (Map.Entry<String, Type> vars : donationContext.getFreeVariables().entrySet()) { final Type type = vars.getValue(); final Type typeWithRestrictedQualifiers = dropQualifiersThatCannotBeUsedForLocalVariable(type); final Initializer initializer; if (isLoopLimiter(vars.getKey(), typeWithRestrictedQualifiers.getWithoutQualifiers())) { initializer = new Initializer(new IntConstantExpr("0")); } else { initializer = getInitializer(injectionPoint, donationContext, typeWithRestrictedQualifiers, true, generator, shadingLanguageVersion); } final ImmutablePair<Type, ArrayInfo> baseTypeAndArrayInfo = Typer.getBaseTypeArrayInfo(typeWithRestrictedQualifiers); donatedStmts.add(new DeclarationStmt( new VariablesDeclaration(baseTypeAndArrayInfo.left, new VariableDeclInfo(vars.getKey(), baseTypeAndArrayInfo.right, initializer)))); } donatedStmts.add(donationContext.getDonorFragment()); BlockStmt donatedStmt = new BlockStmt(donatedStmts, true); new RemoveImmediateBreakStatements(donatedStmt); new RemoveImmediateContinueStatements(donatedStmt); new RemoveImmediateCaseLabels(donatedStmt); new RemoveReturnStatements(donatedStmt); new RemoveDiscardStatements(donatedStmt); return donatedStmt; } DonateLiveCodeTransformation(Function<IRandom, Boolean> probabilityOfDonation,
                                      File donorsDirectory,
                                      GenerationParams generationParams,
                                      boolean allowLongLoops); @Override String getName(); static final String NAME; }
@Test public void prepareStatementToDonateDiscardRemoved() throws Exception { final DonateLiveCodeTransformation dlc = getDummyTransformationObject(); DonationContext dc = new DonationContext(new DiscardStmt(), new HashMap<>(), new ArrayList<>(), null); Stmt donated = dlc.prepareStatementToDonate(null, dc, TransformationProbabilities.DEFAULT_PROBABILITIES, new RandomWrapper(0), ShadingLanguageVersion.ESSL_100); assertFalse(new CheckPredicateVisitor() { @Override public void visitDiscardStmt(DiscardStmt discardStmt) { predicateHolds(); } }.test(donated)); }
@Test public void prepareStatementToDonateTopLevelBreakRemoved() throws Exception { final DonateLiveCodeTransformation dlc = getDummyTransformationObject(); final TranslationUnit donor = ParseHelper.parse("#version 310 es\n" + "void main() {\n" + " for (int i = 0; i < 10; i ++)\n" + " if (i > 5) break;\n" + "}\n"); final TranslationUnit reference = ParseHelper.parse("#version 310 es\n" + "void main() {\n" + " for(int i = 0; i < 100; i++) {\n" + " switch (i) {\n" + " case 0:\n" + " i++;\n" + " default:\n" + " i++;\n" + " }\n" + " }\n" + "}\n"); for (IInjectionPoint injectionPoint : new InjectionPoints(reference, new RandomWrapper(0), item -> true).getAllInjectionPoints()) { final Stmt toDonate = ((ForStmt) donor.getMainFunction().getBody().getStmt(0)).getBody() .clone(); assert toDonate instanceof IfStmt; final DonationContext dc = new DonationContext(toDonate, new HashMap<>(), new ArrayList<>(), donor.getMainFunction()); final Stmt donated = dlc.prepareStatementToDonate(injectionPoint, dc, TransformationProbabilities.DEFAULT_PROBABILITIES, new RandomWrapper(0), ShadingLanguageVersion.ESSL_310); assertEquals("{\n" + " if(i > 5)\n" + " 1;\n" + "}\n", donated.getText()); } }
@Test public void prepareStatementToDonateTopLevelContinueRemoved() throws Exception { final DonateLiveCodeTransformation dlc = getDummyTransformationObject(); final TranslationUnit donor = ParseHelper.parse("#version 100\n" + "void main() {\n" + " for (int i = 0; i < 10; i ++)\n" + " if (i > 5) continue;\n" + "}\n"); final TranslationUnit reference = ParseHelper.parse("#version 100\n" + "void main() {\n" + " for(int i = 0; i < 100; i++) {\n" + " 1;\n" + " }\n" + "}\n"); for (IInjectionPoint injectionPoint : new InjectionPoints(reference, new RandomWrapper(0), item -> true).getAllInjectionPoints()) { final Stmt toDonate = ((ForStmt) donor.getMainFunction().getBody().getStmt(0)).getBody() .clone(); assert toDonate instanceof IfStmt; final DonationContext dc = new DonationContext(toDonate, new HashMap<>(), new ArrayList<>(), donor.getMainFunction()); final Stmt donated = dlc.prepareStatementToDonate(injectionPoint, dc, TransformationProbabilities.DEFAULT_PROBABILITIES, new RandomWrapper(0), ShadingLanguageVersion.ESSL_100); assertEquals("{\n" + " if(i > 5)\n" + " 1;\n" + "}\n", donated.getText()); } }
@Test public void prepareStatementToDonateTopLevelCaseAndDefaultRemoved() throws Exception { final DonateLiveCodeTransformation dlc = getDummyTransformationObject(); final TranslationUnit donor = ParseHelper.parse("#version 310 es\n" + "void main() {\n" + " int x = 3;\n" + " switch (x) {\n" + " case 0:\n" + " x++;\n" + " default:\n" + " x++;\n" + " }\n" + "}\n"); final TranslationUnit reference = ParseHelper.parse("#version 310 es\n" + "void main() {\n" + " switch (0) {\n" + " case 1:\n" + " 1;\n" + " default:\n" + " 2;\n" + " }\n" + "}\n"); for (IInjectionPoint injectionPoint : new InjectionPoints(reference, new RandomWrapper(0), item -> true).getAllInjectionPoints()) { final Stmt toDonate = ((SwitchStmt) donor.getMainFunction().getBody().getStmt(1)).getBody() .clone(); final DonationContext dc = new DonationContext(toDonate, new HashMap<>(), new ArrayList<>(), donor.getMainFunction()); final Stmt donated = dlc.prepareStatementToDonate(injectionPoint, dc, TransformationProbabilities.DEFAULT_PROBABILITIES, new RandomWrapper(0), ShadingLanguageVersion.ESSL_310); assertEquals("{\n" + " {\n" + " 1;\n" + " x ++;\n" + " 1;\n" + " x ++;\n" + " }\n" + "}\n", donated.getText()); } }
@Test public void prepareStatementToDonateBreakFromLoopKept() throws Exception { final DonateLiveCodeTransformation dlc = getDummyTransformationObject(); final TranslationUnit donor = ParseHelper.parse("#version 100\n" + "void main() {\n" + " for (int i = 0; i < 10; i ++)\n" + " if (i > 5) break;\n" + "}\n"); final TranslationUnit reference = ParseHelper.parse("#version 100\n" + "void main() {\n" + " ;\n" + " for(int i = 0; i < 100; i++) {\n" + " }\n" + "}\n"); for (IInjectionPoint injectionPoint : new InjectionPoints(reference, new RandomWrapper(0), item -> true).getAllInjectionPoints()) { final Stmt toDonate = donor.getMainFunction().getBody().getStmt(0) .clone(); assert toDonate instanceof ForStmt; final DonationContext dc = new DonationContext(toDonate, new HashMap<>(), new ArrayList<>(), donor.getMainFunction()); final Stmt donated = dlc.prepareStatementToDonate(injectionPoint, dc, TransformationProbabilities.DEFAULT_PROBABILITIES, new RandomWrapper(0), ShadingLanguageVersion.ESSL_100); assertEquals("{\n" + " for(int i = 0; i < 10; i ++)\n" + " if(i > 5)\n" + " break;\n" + "}\n", donated.getText()); } }
@Test public void prepareStatementToDonateSwitchWithBreakAndDefaultKept() throws Exception { final DonateLiveCodeTransformation dlc = getDummyTransformationObject(); final TranslationUnit donor = ParseHelper.parse("#version 310 es\n" + "void main() {\n" + " switch (0) {\n" + " case 0:\n" + " 1;\n" + " break;\n" + " default:\n" + " 2;\n" + " }\n" + "}\n"); final TranslationUnit reference = ParseHelper.parse("#version 310 es\n" + "void main() {\n" + " ;\n" + " switch (0) {\n" + " case 1:\n" + " 1;\n" + " default:\n" + " 2;\n" + " }\n" + "}\n"); for (IInjectionPoint injectionPoint : new InjectionPoints(reference, new RandomWrapper(0), item -> true).getAllInjectionPoints()) { final Stmt toDonate = donor.getMainFunction().getBody().getStmt(0).clone(); assert toDonate instanceof SwitchStmt; final DonationContext dc = new DonationContext(toDonate, new HashMap<>(), new ArrayList<>(), donor.getMainFunction()); final Stmt donated = dlc.prepareStatementToDonate(injectionPoint, dc, TransformationProbabilities.DEFAULT_PROBABILITIES, new RandomWrapper(0), ShadingLanguageVersion.ESSL_310); assertEquals("{\n" + " switch(0)\n" + " {\n" + " case 0:\n" + " 1;\n" + " break;\n" + " default:\n" + " 2;\n" + " }\n" + "}\n", donated.getText()); } }
@Test public void prepareStatementToDonateContinueInLoopKept() throws Exception { final DonateLiveCodeTransformation dlc = getDummyTransformationObject(); final TranslationUnit donor = ParseHelper.parse("#version 100\n" + "void main() {\n" + " for (int i = 0; i < 10; i ++)\n" + " if (i > 5) continue;\n" + "}\n"); final TranslationUnit reference = ParseHelper.parse("#version 100\n" + "void main() {\n" + " ;\n" + " for(int i = 0; i < 100; i++) {\n" + " }\n" + "}\n"); for (IInjectionPoint injectionPoint : new InjectionPoints(reference, new RandomWrapper(0), item -> true).getAllInjectionPoints()) { final Stmt toDonate = donor.getMainFunction().getBody().getStmt(0).clone(); assert toDonate instanceof ForStmt; DonationContext dc = new DonationContext(toDonate, new HashMap<>(), new ArrayList<>(), donor.getMainFunction()); final Stmt donated = dlc.prepareStatementToDonate(injectionPoint, dc, TransformationProbabilities.DEFAULT_PROBABILITIES, new RandomWrapper(0), ShadingLanguageVersion.ESSL_100); assertEquals("{\n" + " for(int i = 0; i < 10; i ++)\n" + " if(i > 5)\n" + " continue;\n" + "}\n", donated.getText()); } }
@Test public void checkMutateSpecialCase() throws Exception { final String reference = "#version 300 es\n" + "void main() {\n" + " int t;\n" + " {\n" + " }\n" + " gl_FragColor = vec4(float(t));\n" + "}\n"; final IRandom generator = new RandomWrapper(0); for (int i = 0; i < 10; i++) { final DonateLiveCodeTransformation donateLiveCode = new DonateLiveCodeTransformation(item -> true, testFolder.getRoot(), GenerationParams.normal(ShaderKind.FRAGMENT, true), false); final TranslationUnit referenceTu = ParseHelper.parse(reference); BlockInjectionPoint blockInjectionPoint = new ScopeTrackingVisitor() { BlockInjectionPoint blockInjectionPoint; @Override public void visitBlockStmt(BlockStmt stmt) { super.visitBlockStmt(stmt); if (stmt.getNumStmts() == 0) { blockInjectionPoint = new BlockInjectionPoint(stmt, null, getEnclosingFunction(), false, false, getCurrentScope()); } } BlockInjectionPoint getBlockInjectionPoint(TranslationUnit tu) { visit(tu); return blockInjectionPoint; } }.getBlockInjectionPoint(referenceTu); final DeclarationStmt declarationStmt = new DeclarationStmt( new VariablesDeclaration( BasicType.INT, new VariableDeclInfo("a", null, new Initializer( new BinaryExpr( new BinaryExpr( new BinaryExpr( new BinaryExpr( new VariableIdentifierExpr("x1"), new VariableIdentifierExpr("x2"), BinOp.ADD ), new VariableIdentifierExpr("x3"), BinOp.ADD ), new VariableIdentifierExpr("x4"), BinOp.ADD ), new VariableIdentifierExpr("x5"), BinOp.ADD ) ) ))); final Map<String, Type> freeVariables = new HashMap<>(); freeVariables.put("x1", BasicType.INT); freeVariables.put("x2", BasicType.INT); freeVariables.put("x3", BasicType.INT); freeVariables.put("x4", BasicType.INT); freeVariables.put("x5", BasicType.INT); Stmt toDonate = donateLiveCode.prepareStatementToDonate(blockInjectionPoint, new DonationContext( declarationStmt, freeVariables, new ArrayList<>(), new FunctionDefinition(new FunctionPrototype("foo", VoidType.VOID, new ArrayList<>()), null)), TransformationProbabilities.onlyLiveCodeAlwaysSubstitute(), generator, referenceTu.getShadingLanguageVersion()); blockInjectionPoint.inject(toDonate); final IdentityTransformation identityTransformation = new IdentityTransformation(); identityTransformation.apply(referenceTu, TransformationProbabilities.onlyMutateExpressions(), generator, GenerationParams.large(ShaderKind.FRAGMENT, true) ); } }