@Test public void doNotAddDeclarationsIfNothingToTruncate() throws Exception { final String shader = "#version 310 es\n" + "void main() {\n" + " do {\n" + " } while(false);\n" + "}\n"; final ShaderJob shaderJob = new GlslShaderJob(Optional.empty(), new PipelineInfo(), ParseHelper.parse(shader, ShaderKind.VERTEX), ParseHelper.parse(shader, ShaderKind.FRAGMENT)); GloballyTruncateLoops.truncate(shaderJob, 100, "LOOP_COUNT", "LOOP_BOUND"); for (TranslationUnit tu : shaderJob.getShaders()) { CompareAsts.assertEqualAsts(shader, tu); } }
public static void truncate(ShaderJob shaderJob, int loopLimit, String loopCountName, String loopBoundName) { for (TranslationUnit tu : shaderJob.getShaders()) { final boolean globalDeclarationsAreNecessary = new StandardVisitor() { private boolean appliedAtLeastOneTruncation = false; private Expr buildCondition(Expr originalCondition) { return new BinaryExpr( new ParenExpr(originalCondition), new ParenExpr( new BinaryExpr(new VariableIdentifierExpr(loopCountName), new VariableIdentifierExpr(loopBoundName), BinOp.LT)), BinOp.LAND); } private boolean isFalseLiteral(Expr conditionExpr) { return !(conditionExpr instanceof BoolConstantExpr && !((BoolConstantExpr)conditionExpr).getIsTrue()); } private void handleLoopStmt(LoopStmt loopStmt, boolean newScope) { if (isFalseLiteral(loopStmt.getCondition())) { appliedAtLeastOneTruncation = true; loopStmt.setCondition(buildCondition(loopStmt.getCondition())); if (!(loopStmt.getBody() instanceof BlockStmt)) { loopStmt.setBody(new BlockStmt(Collections.singletonList(loopStmt.getBody()), newScope)); } ((BlockStmt) loopStmt.getBody()).insertStmt(0, new ExprStmt(new UnaryExpr(new VariableIdentifierExpr(loopCountName), UnOp.POST_INC))); } } @Override public void visitForStmt(ForStmt forStmt) { handleLoopStmt(forStmt, true); super.visitForStmt(forStmt); } @Override public void visitWhileStmt(WhileStmt whileStmt) { handleLoopStmt(whileStmt, false); super.visitWhileStmt(whileStmt); } @Override public void visitDoStmt(DoStmt doStmt) { handleLoopStmt(doStmt, true); super.visitDoStmt(doStmt); } private boolean truncate(TranslationUnit tu) { visit(tu); return appliedAtLeastOneTruncation; } }.truncate(tu); if (globalDeclarationsAreNecessary) { Declaration firstNonPrecisionDeclaration = null; for (Declaration decl : tu.getTopLevelDeclarations()) { if (decl instanceof PrecisionDeclaration) { continue; } firstNonPrecisionDeclaration = decl; break; } assert firstNonPrecisionDeclaration != null; tu.addDeclarationBefore(new VariablesDeclaration(new QualifiedType(BasicType.INT, Arrays.asList(TypeQualifier.CONST)), new VariableDeclInfo(loopBoundName, null, new Initializer(new IntConstantExpr(new Integer(loopLimit).toString())))), firstNonPrecisionDeclaration); tu.addDeclarationBefore(new VariablesDeclaration(BasicType.INT, new VariableDeclInfo(loopCountName, null, new Initializer(new IntConstantExpr("0")))), firstNonPrecisionDeclaration); } } }
GloballyTruncateLoops { public static void truncate(ShaderJob shaderJob, int loopLimit, String loopCountName, String loopBoundName) { for (TranslationUnit tu : shaderJob.getShaders()) { final boolean globalDeclarationsAreNecessary = new StandardVisitor() { private boolean appliedAtLeastOneTruncation = false; private Expr buildCondition(Expr originalCondition) { return new BinaryExpr( new ParenExpr(originalCondition), new ParenExpr( new BinaryExpr(new VariableIdentifierExpr(loopCountName), new VariableIdentifierExpr(loopBoundName), BinOp.LT)), BinOp.LAND); } private boolean isFalseLiteral(Expr conditionExpr) { return !(conditionExpr instanceof BoolConstantExpr && !((BoolConstantExpr)conditionExpr).getIsTrue()); } private void handleLoopStmt(LoopStmt loopStmt, boolean newScope) { if (isFalseLiteral(loopStmt.getCondition())) { appliedAtLeastOneTruncation = true; loopStmt.setCondition(buildCondition(loopStmt.getCondition())); if (!(loopStmt.getBody() instanceof BlockStmt)) { loopStmt.setBody(new BlockStmt(Collections.singletonList(loopStmt.getBody()), newScope)); } ((BlockStmt) loopStmt.getBody()).insertStmt(0, new ExprStmt(new UnaryExpr(new VariableIdentifierExpr(loopCountName), UnOp.POST_INC))); } } @Override public void visitForStmt(ForStmt forStmt) { handleLoopStmt(forStmt, true); super.visitForStmt(forStmt); } @Override public void visitWhileStmt(WhileStmt whileStmt) { handleLoopStmt(whileStmt, false); super.visitWhileStmt(whileStmt); } @Override public void visitDoStmt(DoStmt doStmt) { handleLoopStmt(doStmt, true); super.visitDoStmt(doStmt); } private boolean truncate(TranslationUnit tu) { visit(tu); return appliedAtLeastOneTruncation; } }.truncate(tu); if (globalDeclarationsAreNecessary) { Declaration firstNonPrecisionDeclaration = null; for (Declaration decl : tu.getTopLevelDeclarations()) { if (decl instanceof PrecisionDeclaration) { continue; } firstNonPrecisionDeclaration = decl; break; } assert firstNonPrecisionDeclaration != null; tu.addDeclarationBefore(new VariablesDeclaration(new QualifiedType(BasicType.INT, Arrays.asList(TypeQualifier.CONST)), new VariableDeclInfo(loopBoundName, null, new Initializer(new IntConstantExpr(new Integer(loopLimit).toString())))), firstNonPrecisionDeclaration); tu.addDeclarationBefore(new VariablesDeclaration(BasicType.INT, new VariableDeclInfo(loopCountName, null, new Initializer(new IntConstantExpr("0")))), firstNonPrecisionDeclaration); } } } }
GloballyTruncateLoops { public static void truncate(ShaderJob shaderJob, int loopLimit, String loopCountName, String loopBoundName) { for (TranslationUnit tu : shaderJob.getShaders()) { final boolean globalDeclarationsAreNecessary = new StandardVisitor() { private boolean appliedAtLeastOneTruncation = false; private Expr buildCondition(Expr originalCondition) { return new BinaryExpr( new ParenExpr(originalCondition), new ParenExpr( new BinaryExpr(new VariableIdentifierExpr(loopCountName), new VariableIdentifierExpr(loopBoundName), BinOp.LT)), BinOp.LAND); } private boolean isFalseLiteral(Expr conditionExpr) { return !(conditionExpr instanceof BoolConstantExpr && !((BoolConstantExpr)conditionExpr).getIsTrue()); } private void handleLoopStmt(LoopStmt loopStmt, boolean newScope) { if (isFalseLiteral(loopStmt.getCondition())) { appliedAtLeastOneTruncation = true; loopStmt.setCondition(buildCondition(loopStmt.getCondition())); if (!(loopStmt.getBody() instanceof BlockStmt)) { loopStmt.setBody(new BlockStmt(Collections.singletonList(loopStmt.getBody()), newScope)); } ((BlockStmt) loopStmt.getBody()).insertStmt(0, new ExprStmt(new UnaryExpr(new VariableIdentifierExpr(loopCountName), UnOp.POST_INC))); } } @Override public void visitForStmt(ForStmt forStmt) { handleLoopStmt(forStmt, true); super.visitForStmt(forStmt); } @Override public void visitWhileStmt(WhileStmt whileStmt) { handleLoopStmt(whileStmt, false); super.visitWhileStmt(whileStmt); } @Override public void visitDoStmt(DoStmt doStmt) { handleLoopStmt(doStmt, true); super.visitDoStmt(doStmt); } private boolean truncate(TranslationUnit tu) { visit(tu); return appliedAtLeastOneTruncation; } }.truncate(tu); if (globalDeclarationsAreNecessary) { Declaration firstNonPrecisionDeclaration = null; for (Declaration decl : tu.getTopLevelDeclarations()) { if (decl instanceof PrecisionDeclaration) { continue; } firstNonPrecisionDeclaration = decl; break; } assert firstNonPrecisionDeclaration != null; tu.addDeclarationBefore(new VariablesDeclaration(new QualifiedType(BasicType.INT, Arrays.asList(TypeQualifier.CONST)), new VariableDeclInfo(loopBoundName, null, new Initializer(new IntConstantExpr(new Integer(loopLimit).toString())))), firstNonPrecisionDeclaration); tu.addDeclarationBefore(new VariablesDeclaration(BasicType.INT, new VariableDeclInfo(loopCountName, null, new Initializer(new IntConstantExpr("0")))), firstNonPrecisionDeclaration); } } }  }
GloballyTruncateLoops { public static void truncate(ShaderJob shaderJob, int loopLimit, String loopCountName, String loopBoundName) { for (TranslationUnit tu : shaderJob.getShaders()) { final boolean globalDeclarationsAreNecessary = new StandardVisitor() { private boolean appliedAtLeastOneTruncation = false; private Expr buildCondition(Expr originalCondition) { return new BinaryExpr( new ParenExpr(originalCondition), new ParenExpr( new BinaryExpr(new VariableIdentifierExpr(loopCountName), new VariableIdentifierExpr(loopBoundName), BinOp.LT)), BinOp.LAND); } private boolean isFalseLiteral(Expr conditionExpr) { return !(conditionExpr instanceof BoolConstantExpr && !((BoolConstantExpr)conditionExpr).getIsTrue()); } private void handleLoopStmt(LoopStmt loopStmt, boolean newScope) { if (isFalseLiteral(loopStmt.getCondition())) { appliedAtLeastOneTruncation = true; loopStmt.setCondition(buildCondition(loopStmt.getCondition())); if (!(loopStmt.getBody() instanceof BlockStmt)) { loopStmt.setBody(new BlockStmt(Collections.singletonList(loopStmt.getBody()), newScope)); } ((BlockStmt) loopStmt.getBody()).insertStmt(0, new ExprStmt(new UnaryExpr(new VariableIdentifierExpr(loopCountName), UnOp.POST_INC))); } } @Override public void visitForStmt(ForStmt forStmt) { handleLoopStmt(forStmt, true); super.visitForStmt(forStmt); } @Override public void visitWhileStmt(WhileStmt whileStmt) { handleLoopStmt(whileStmt, false); super.visitWhileStmt(whileStmt); } @Override public void visitDoStmt(DoStmt doStmt) { handleLoopStmt(doStmt, true); super.visitDoStmt(doStmt); } private boolean truncate(TranslationUnit tu) { visit(tu); return appliedAtLeastOneTruncation; } }.truncate(tu); if (globalDeclarationsAreNecessary) { Declaration firstNonPrecisionDeclaration = null; for (Declaration decl : tu.getTopLevelDeclarations()) { if (decl instanceof PrecisionDeclaration) { continue; } firstNonPrecisionDeclaration = decl; break; } assert firstNonPrecisionDeclaration != null; tu.addDeclarationBefore(new VariablesDeclaration(new QualifiedType(BasicType.INT, Arrays.asList(TypeQualifier.CONST)), new VariableDeclInfo(loopBoundName, null, new Initializer(new IntConstantExpr(new Integer(loopLimit).toString())))), firstNonPrecisionDeclaration); tu.addDeclarationBefore(new VariablesDeclaration(BasicType.INT, new VariableDeclInfo(loopCountName, null, new Initializer(new IntConstantExpr("0")))), firstNonPrecisionDeclaration); } } }  static void truncate(ShaderJob shaderJob, int loopLimit, String loopCountName,
                              String loopBoundName); }
GloballyTruncateLoops { public static void truncate(ShaderJob shaderJob, int loopLimit, String loopCountName, String loopBoundName) { for (TranslationUnit tu : shaderJob.getShaders()) { final boolean globalDeclarationsAreNecessary = new StandardVisitor() { private boolean appliedAtLeastOneTruncation = false; private Expr buildCondition(Expr originalCondition) { return new BinaryExpr( new ParenExpr(originalCondition), new ParenExpr( new BinaryExpr(new VariableIdentifierExpr(loopCountName), new VariableIdentifierExpr(loopBoundName), BinOp.LT)), BinOp.LAND); } private boolean isFalseLiteral(Expr conditionExpr) { return !(conditionExpr instanceof BoolConstantExpr && !((BoolConstantExpr)conditionExpr).getIsTrue()); } private void handleLoopStmt(LoopStmt loopStmt, boolean newScope) { if (isFalseLiteral(loopStmt.getCondition())) { appliedAtLeastOneTruncation = true; loopStmt.setCondition(buildCondition(loopStmt.getCondition())); if (!(loopStmt.getBody() instanceof BlockStmt)) { loopStmt.setBody(new BlockStmt(Collections.singletonList(loopStmt.getBody()), newScope)); } ((BlockStmt) loopStmt.getBody()).insertStmt(0, new ExprStmt(new UnaryExpr(new VariableIdentifierExpr(loopCountName), UnOp.POST_INC))); } } @Override public void visitForStmt(ForStmt forStmt) { handleLoopStmt(forStmt, true); super.visitForStmt(forStmt); } @Override public void visitWhileStmt(WhileStmt whileStmt) { handleLoopStmt(whileStmt, false); super.visitWhileStmt(whileStmt); } @Override public void visitDoStmt(DoStmt doStmt) { handleLoopStmt(doStmt, true); super.visitDoStmt(doStmt); } private boolean truncate(TranslationUnit tu) { visit(tu); return appliedAtLeastOneTruncation; } }.truncate(tu); if (globalDeclarationsAreNecessary) { Declaration firstNonPrecisionDeclaration = null; for (Declaration decl : tu.getTopLevelDeclarations()) { if (decl instanceof PrecisionDeclaration) { continue; } firstNonPrecisionDeclaration = decl; break; } assert firstNonPrecisionDeclaration != null; tu.addDeclarationBefore(new VariablesDeclaration(new QualifiedType(BasicType.INT, Arrays.asList(TypeQualifier.CONST)), new VariableDeclInfo(loopBoundName, null, new Initializer(new IntConstantExpr(new Integer(loopLimit).toString())))), firstNonPrecisionDeclaration); tu.addDeclarationBefore(new VariablesDeclaration(BasicType.INT, new VariableDeclInfo(loopCountName, null, new Initializer(new IntConstantExpr("0")))), firstNonPrecisionDeclaration); } } }  static void truncate(ShaderJob shaderJob, int loopLimit, String loopCountName,
                              String loopBoundName);  }