Skip to content

Commit

Permalink
Fix generator (#86)
Browse files Browse the repository at this point in the history
* Fixed some problems related to the handling of structs in the generator.
  • Loading branch information
afd authored Oct 26, 2018
1 parent 2a8d721 commit 622e2b8
Show file tree
Hide file tree
Showing 18 changed files with 308 additions and 33 deletions.
37 changes: 37 additions & 0 deletions ast/src/main/java/com/graphicsfuzz/common/typing/Scope.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.graphicsfuzz.common.ast.decl.ParameterDecl;
import com.graphicsfuzz.common.ast.decl.VariableDeclInfo;
import com.graphicsfuzz.common.ast.decl.VariablesDeclaration;
import com.graphicsfuzz.common.ast.type.StructDefinitionType;
import com.graphicsfuzz.common.ast.type.Type;
import java.util.ArrayList;
import java.util.Collections;
Expand All @@ -31,10 +32,12 @@
public class Scope {

private final Map<String, ScopeEntry> variableMapping;
private final Map<String, StructDefinitionType> structMapping;
private final Scope parent;

public Scope(Scope parent) {
this.variableMapping = new HashMap<>();
this.structMapping = new HashMap<>();
this.parent = parent;
}

Expand All @@ -50,6 +53,26 @@ public void add(String name, Type type, Optional<ParameterDecl> parameterDecl) {
variableMapping.put(name, new ScopeEntry(type, parameterDecl));
}

public void addStructDefinition(StructDefinitionType sdt) {
assert sdt.hasStructNameType();
structMapping.put(sdt.getStructNameType().getName(), sdt);
}

/**
* Look in current scope to see whether we have a struct definition type matching the struct name.
* @param structName Name of struct type.
* @return Corresponding struct definition, if found, otherwise null.
*/
public StructDefinitionType lookupStructName(String structName) {
if (structMapping.containsKey(structName)) {
return structMapping.get(structName);
}
if (hasParent()) {
return getParent().lookupStructName(structName);
}
return null;
}

private void checkNameTypeAndParam(String name, Type type,
Optional<ParameterDecl> parameterDecl) {
if (type == null) {
Expand Down Expand Up @@ -97,6 +120,17 @@ public List<String> namesOfAllVariablesInScope() {
return Collections.unmodifiableList(result);
}

public List<String> namesOfAllStructDefinitionsInScope() {
List<String> result = new ArrayList<>();
Scope scope = this;
while (scope != null) {
result.addAll(scope.structMapping.keySet());
scope = scope.parent;
}
result.sort(String::compareTo);
return Collections.unmodifiableList(result);
}

public List<String> keys() {
List<String> result = new ArrayList<>();
result.addAll(variableMapping.keySet());
Expand All @@ -117,6 +151,9 @@ public Scope shallowClone() {
for (Entry<String, ScopeEntry> entry : variableMapping.entrySet()) {
result.variableMapping.put(entry.getKey(), entry.getValue());
}
for (Entry<String, StructDefinitionType> entry : structMapping.entrySet()) {
result.structMapping.put(entry.getKey(), entry.getValue());
}
return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,13 @@

public abstract class ScopeTreeBuilder extends StandardVisitor {

protected final Map<StructNameType, StructDefinitionType> structDeclarations;
protected Scope currentScope;
private Deque<BlockStmt> enclosingBlocks;
private boolean addEncounteredParametersToScope;
protected FunctionDefinition enclosingFunction;
private List<FunctionPrototype> encounteredFunctionPrototypes;

protected ScopeTreeBuilder() {
this.structDeclarations = new HashMap<>();
this.currentScope = new Scope(null);
this.enclosingBlocks = new LinkedList<>();
this.addEncounteredParametersToScope = false;
Expand All @@ -59,7 +57,7 @@ protected ScopeTreeBuilder() {
public void visitStructDefinitionType(StructDefinitionType structDefinitionType) {
super.visitStructDefinitionType(structDefinitionType);
if (structDefinitionType.hasStructNameType()) {
structDeclarations.put(structDefinitionType.getStructNameType(), structDefinitionType);
currentScope.addStructDefinition(structDefinitionType);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
import com.graphicsfuzz.common.ast.decl.VariableDeclInfo;
import com.graphicsfuzz.common.ast.decl.VariablesDeclaration;
import com.graphicsfuzz.common.ast.expr.VariableIdentifierExpr;
import com.graphicsfuzz.common.ast.type.StructDefinitionType;
import com.graphicsfuzz.common.ast.type.StructNameType;
import com.graphicsfuzz.common.ast.type.Type;
import com.graphicsfuzz.common.typing.ScopeEntry;
import com.graphicsfuzz.common.typing.ScopeTreeBuilder;
import com.graphicsfuzz.util.Constants;
Expand All @@ -35,14 +38,35 @@ public static void strip(TranslationUnit tu) {
new StripUnusedGlobals(tu);
}

private Set<VariableDeclInfo> unusedGlobals;
private final Set<VariableDeclInfo> unusedGlobals;
private final Set<StructDefinitionType> unusedStructs;

private StripUnusedGlobals(TranslationUnit tu) {
this.unusedGlobals = new HashSet<>();
this.unusedStructs = new HashSet<>();
visit(tu);
sweep(tu);
}

@Override
public void visitVariablesDeclaration(VariablesDeclaration variablesDeclaration) {
if (variablesDeclaration.getBaseType().getWithoutQualifiers() instanceof StructDefinitionType) {
final StructDefinitionType sdt =
(StructDefinitionType) variablesDeclaration.getBaseType().getWithoutQualifiers();
if (sdt.hasStructNameType()) {
// Initially, assume it is unused
unusedStructs.add(sdt);
}
}
super.visitVariablesDeclaration(variablesDeclaration);
}

@Override
public void visitStructNameType(StructNameType structNameType) {
super.visitStructNameType(structNameType);
unusedStructs.remove(currentScope.lookupStructName(structNameType.getName()));
}

@Override
public void visitVariableDeclInfo(VariableDeclInfo variableDeclInfo) {
super.visitVariableDeclInfo(variableDeclInfo);
Expand Down Expand Up @@ -78,10 +102,19 @@ private void sweep(TranslationUnit tu) {
index++;
}
}
if (variablesDeclaration.getNumDecls() == 0) {
if (variablesDeclaration.getNumDecls() == 0
&& !isUsedStructType(variablesDeclaration.getBaseType())) {
tu.removeTopLevelDeclaration(variablesDeclaration);
}
}
}

private boolean isUsedStructType(Type type) {
if (!(type.getWithoutQualifiers() instanceof StructDefinitionType)) {
return false;
}
final StructDefinitionType sdt = (StructDefinitionType) type.getWithoutQualifiers();
return !unusedStructs.contains(sdt);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@

package com.graphicsfuzz.common.util;

import static org.junit.Assert.assertEquals;

import com.graphicsfuzz.common.ast.TranslationUnit;
import com.graphicsfuzz.common.tool.PrettyPrinterVisitor;
import org.junit.Test;

public class StripUnusedGlobalsTest {
Expand Down Expand Up @@ -55,8 +52,19 @@ public void testStripUnusedGlobals() throws Exception {
+ "}";
final TranslationUnit tu = ParseHelper.parse(original);
StripUnusedGlobals.strip(tu);
assertEquals(PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(expected)),
PrettyPrinterVisitor.prettyPrintAsString(tu));
CompareAsts.assertEqualAsts(expected, tu);
}

@Test
public void testDoNotStripStruct() throws Exception {
final String original = ""
+ "struct S { int a; };"
+ "void main() {"
+ " S myS;"
+ "}";
final TranslationUnit tu = ParseHelper.parse(original);
StripUnusedGlobals.strip(tu);
CompareAsts.assertEqualAsts(original, tu);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.graphicsfuzz.common.ast.decl.VariablesDeclaration;
import com.graphicsfuzz.common.ast.expr.ArrayConstructorExpr;
import com.graphicsfuzz.common.ast.expr.Expr;
import com.graphicsfuzz.common.ast.expr.TypeConstructorExpr;
import com.graphicsfuzz.common.ast.stmt.BlockStmt;
import com.graphicsfuzz.common.ast.stmt.BreakStmt;
import com.graphicsfuzz.common.ast.stmt.ContinueStmt;
Expand Down Expand Up @@ -184,6 +185,18 @@ private Expr makeExpr(Type targetType, boolean isLValue, boolean constContext, f
throw new FuzzedIntoACornerException();
}
}
if (targetType instanceof StructNameType) {
final String structName = ((StructNameType) targetType).getName();
final StructDefinitionType sdt =
fuzzingContext.getCurrentScope().lookupStructName(structName);
if (sdt == null) {
throw new RuntimeException("Could not find a struct named " + structName + " in scope.");
}
assert sdt.getStructNameType().getName().equals(structName);
return new TypeConstructorExpr(structName, sdt.getFieldTypes()
.stream().map(item -> makeExpr(item, false, constContext, depth + 1))
.collect(Collectors.toList()));
}
throw new RuntimeException("Do not yet know how to make expr of type " + targetType.getClass());

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.graphicsfuzz.common.ast.type.TypeQualifier;
import com.graphicsfuzz.common.glslversion.ShadingLanguageVersion;
import com.graphicsfuzz.common.transformreduce.ShaderJob;
import com.graphicsfuzz.common.typing.Typer;
import com.graphicsfuzz.common.util.IRandom;
import com.graphicsfuzz.common.util.IdGenerator;
import com.graphicsfuzz.common.util.ParseTimeoutException;
Expand Down Expand Up @@ -380,6 +381,7 @@ private static String applyTransformationsMultiPass(GeneratorArguments args,
// Keep the size down by stripping unused stuff.
StripUnusedFunctions.strip(reference);
StripUnusedGlobals.strip(reference);
assert canTypeCheckWithoutFailure(reference, args.getShadingLanguageVersion());
done.add(transformation);
if (transformations.isEmpty()) {
transformations = done;
Expand All @@ -389,6 +391,14 @@ private static String applyTransformationsMultiPass(GeneratorArguments args,
return result;
}

private static boolean canTypeCheckWithoutFailure(TranslationUnit reference,
ShadingLanguageVersion shadingLanguageVersion) {
// Debugging aid: fail early if we end up messing up the translation unit so that type checking
// does not work.
new Typer(reference, shadingLanguageVersion);
return true;
}

private static boolean shaderLargeEnough(TranslationUnit tu, IRandom generator) {
final StatsVisitor statsVisitor = new StatsVisitor(tu);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.graphicsfuzz.common.ast.type.TypeQualifier;
import com.graphicsfuzz.common.ast.visitors.StandardVisitor;
import com.graphicsfuzz.common.glslversion.ShadingLanguageVersion;
import com.graphicsfuzz.common.typing.Scope;
import com.graphicsfuzz.common.typing.ScopeTreeBuilder;
import com.graphicsfuzz.common.typing.Typer;
import com.graphicsfuzz.common.util.IRandom;
Expand Down Expand Up @@ -284,15 +285,28 @@ Map<String, Type> getGlobalsFromShader(TranslationUnit shader) {
}.getGlobalsFromShader(shader);
}

final ScalarInitializer getScalarInitializer(IInjectionPoint injectionPoint, Type type,
boolean restrictToConst, IRandom generator, ShadingLanguageVersion shadingLanguageVersion) {
final boolean isConst = type instanceof QualifiedType && ((QualifiedType) type)
.hasQualifier(TypeQualifier.CONST);
final ScalarInitializer getScalarInitializer(IInjectionPoint injectionPoint,
DonationContext donationContext,
Type type,
boolean restrictToConst,
IRandom generator,
ShadingLanguageVersion shadingLanguageVersion) {
final boolean isConst = type.hasQualifier(TypeQualifier.CONST);
try {

// We may need to generate an initializer for a free variable of struct type. The struct
// will be present in the donor but not yet added to the recipient. We thus make a
// temporary scope identical to the scope at the injection point, but with all of the
// structs from the donation context added.
final Scope scopeForFuzzing = injectionPoint.scopeAtInjectionPoint().shallowClone();
for (StructDefinitionType sdt : donationContext.getAvailableStructs()) {
scopeForFuzzing.addStructDefinition(sdt);
}

return new ScalarInitializer(
new OpaqueExpressionGenerator(generator, generationParams, shadingLanguageVersion)
.fuzzedConstructor(
new Fuzzer(new FuzzingContext(injectionPoint.scopeAtInjectionPoint()),
new Fuzzer(new FuzzingContext(scopeForFuzzing),
shadingLanguageVersion,
generator,
generationParams)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,14 @@ Stmt prepareStatementToDonate(IInjectionPoint injectionPoint, DonationContext do
String newName = "donor_replacement" + name;
substitution.put(name, newName);

final ScalarInitializer initializer = getScalarInitializer(injectionPoint, type,
type instanceof QualifiedType && ((QualifiedType) type)
final ScalarInitializer initializer = getScalarInitializer(
injectionPoint,
donationContext,
type,
type instanceof QualifiedType && ((QualifiedType) type)
.hasQualifier(TypeQualifier.CONST),
generator, shadingLanguageVersion);
generator,
shadingLanguageVersion);

donatedStmts.add(new DeclarationStmt(
new VariablesDeclaration(dropQualifiersThatCannotBeUsedForLocalVariable(type),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Stmt prepareStatementToDonate(IInjectionPoint injectionPoint,
if (isLoopLimiter(vars.getKey(), type.getWithoutQualifiers())) {
initializer = new ScalarInitializer(new IntConstantExpr("0"));
} else {
initializer = getScalarInitializer(injectionPoint, type, true,
initializer = getScalarInitializer(injectionPoint, donationContext, type, true,
generator, shadingLanguageVersion);
}
donatedStmts.add(new DeclarationStmt(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,29 @@
import com.graphicsfuzz.common.ast.expr.ArrayIndexExpr;
import com.graphicsfuzz.common.ast.expr.VariableIdentifierExpr;
import com.graphicsfuzz.common.ast.stmt.Stmt;
import com.graphicsfuzz.common.ast.type.StructDefinitionType;
import com.graphicsfuzz.common.ast.type.Type;
import com.graphicsfuzz.common.ast.visitors.StandardVisitor;
import com.graphicsfuzz.common.typing.ScopeTreeBuilder;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

class DonationContext {

private Stmt donorFragment;
private Map<String, Type> freeVariables;
private FunctionDefinition enclosingFunction;
private final Stmt donorFragment;
private final Map<String, Type> freeVariables;
private final List<StructDefinitionType> availableStructs;
private final FunctionDefinition enclosingFunction;

DonationContext(Stmt donorFragment, Map<String, Type> freeVariables,
List<StructDefinitionType> availableStructs,
FunctionDefinition enclosingFunction) {
this.donorFragment = donorFragment;
this.freeVariables = freeVariables;
this.availableStructs = availableStructs;
this.enclosingFunction = enclosingFunction;
}

Expand All @@ -51,6 +56,10 @@ Map<String, Type> getFreeVariables() {
return Collections.unmodifiableMap(freeVariables);
}

List<StructDefinitionType> getAvailableStructs() {
return Collections.unmodifiableList(availableStructs);
}

FunctionDefinition getEnclosingFunction() {
return enclosingFunction;
}
Expand Down
Loading

0 comments on commit 622e2b8

Please sign in to comment.