Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Fuzzlyn/Fuzzlyn.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Version>2.8</Version>
<Version>2.9</Version>
<TieredCompilation>false</TieredCompilation>
<RuntimeIdentifiers>win-x64;win-x86;linux-arm64;linux-arm;osx-arm64</RuntimeIdentifiers>
<LangVersion>preview</LangVersion>
Expand Down
6 changes: 5 additions & 1 deletion Fuzzlyn/FuzzlynOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ internal class FuzzlynOptions
= new TableDistribution(new Dictionary<int, double>
{
[(int)StatementKind.Assignment] = 0.57,
[(int)StatementKind.If] = 0.14,
[(int)StatementKind.If] = 0.135,
[(int)StatementKind.Switch] = 0.005,
[(int)StatementKind.Block] = 0.1,
[(int)StatementKind.Call] = 0.1,
[(int)StatementKind.Throw] = 0.005,
Expand Down Expand Up @@ -109,6 +110,7 @@ internal class FuzzlynOptions
public double PickLiteralFromTableProb { get; set; } = 0.5;
public double ForLoopProb { get; set; } = 0.8;
public double UpCountedLoopProb { get; set; } = 0.5;
public double SmallLoopIterationCountProb { get; set; } = 0.25;

public ProbabilityDistribution SignedIntegerTypicalLiteralDist { get; set; }
= new TableDistribution(new Dictionary<int, double>
Expand Down Expand Up @@ -245,6 +247,8 @@ internal class FuzzlynOptions
[(int)VectorCreationKind.CreateBroadcast] = 0.44,
[(int)VectorCreationKind.CreateScalar] = 0.44,
});

public ProbabilityDistribution SwitchCaseCountDist { get; set; } = new GeometricDistribution(0.2, 5);
}

internal enum AggregateFieldKind
Expand Down
2 changes: 1 addition & 1 deletion Fuzzlyn/LiteralGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public static (ExpressionSyntax, ExpressionSyntax) GenPrimitiveLiteralLoopBounds
kind = (TypicalLiteralKind)random.Options.SignedIntegerTypicalLiteralDist.Sample(random.Rng);
}

return primType.Info.GenTypicalLiteralLoopBounds(kind);
return primType.Info.GenTypicalLiteralLoopBounds(kind, random);
}

private static List<int> GenArrayDimensions(Randomizer random, ArrayType at)
Expand Down
56 changes: 55 additions & 1 deletion Fuzzlyn/Methods/FuncBodyGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@ private StatementSyntax GenStatement(bool allowReturn = true)
StatementKind kind =
(StatementKind)Options.StatementTypeDist.Sample(_random.Rng);

if ((kind == StatementKind.Block || kind == StatementKind.If || kind == StatementKind.TryCatch || kind == StatementKind.TryFinally || kind == StatementKind.Loop) &&
if ((kind == StatementKind.Block ||
kind == StatementKind.If ||
kind == StatementKind.Switch ||
kind == StatementKind.TryCatch ||
kind == StatementKind.TryFinally ||
kind == StatementKind.Loop) &&
ShouldRejectRecursion())
continue;

Expand All @@ -81,6 +86,8 @@ private StatementSyntax GenStatement(bool allowReturn = true)
return GenCallStatement(tryExisting: ShouldRejectRecursion());
case StatementKind.If:
return GenIf();
case StatementKind.Switch:
return GenSwitch();
case StatementKind.Throw:
return GenThrow();
case StatementKind.TryCatch:
Expand Down Expand Up @@ -333,6 +340,52 @@ private StatementSyntax GenIf()
return gen;
}

private StatementSyntax GenSwitch()
{
ExpressionSyntax guard;
int attempts = 0;
do
{
guard = GenExpression(new PrimitiveType(SyntaxKind.IntKeyword));
} while (IsLiteralOrCastOfLiteral(guard) && attempts++ < 20);

// C# has a rich 'switch' syntax. Here, for now, generate only a simple switch on int type with dense
// numeric cases, to attempt to get Roslyn to generate a 'switch' IL instruction.

List<SwitchSectionSyntax> switchSections = new();
int caseCount = Options.SwitchCaseCountDist.Sample(_random.Rng);
for (int caseNumber = 0; caseNumber < caseCount; caseNumber++)
{
ExpressionSyntax caseValue = LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(caseNumber));
switchSections.Add(
SwitchSection()
.WithLabels(
SingletonList<SwitchLabelSyntax>(
CaseSwitchLabel(caseValue)))
.WithStatements(
List<StatementSyntax>(
new StatementSyntax[] {
GenBlock(),
BreakStatement() })));
}

// Add a default case (which is mostly likely what will get executed when we run).
switchSections.Add(
SwitchSection()
.WithLabels(
SingletonList<SwitchLabelSyntax>(
DefaultSwitchLabel()))
.WithStatements(
List<StatementSyntax>(
new StatementSyntax[] {
GenBlock(),
BreakStatement() })));

SyntaxList<SwitchSectionSyntax> switchSectionSyntax = switchSections.ToSyntaxList();
StatementSyntax gen = SwitchStatement(guard, switchSectionSyntax);
return gen;
}

private StatementSyntax GenThrow()
{
Debug.Assert(_tryCatchCount > 0);
Expand Down Expand Up @@ -1341,6 +1394,7 @@ internal enum StatementKind
Assignment,
Call,
If,
Switch,
Return,
Throw,
TryCatch,
Expand Down
3 changes: 3 additions & 0 deletions Fuzzlyn/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ private static void Main(string[] args)
}
else if (options.Stats)
{
if (options.GenExtensions == null)
options.GenExtensions = []; // No extension by default with --stats

GenerateProgramsAndGetStats(options);
}
else
Expand Down
20 changes: 20 additions & 0 deletions Fuzzlyn/Reduction/Reducer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1323,6 +1323,26 @@ private IEnumerable<SyntaxNode> SimplifyIf(SyntaxNode node)
}
}

[Simplifier]
private IEnumerable<SyntaxNode> SimplifySwitch(SyntaxNode node)
{
if (node is not SwitchStatementSyntax @switch)
yield break;

foreach (var section in @switch.Sections)
{
// Remove the 'break;' statement
if (section.Statements.Count > 0)
{
var lastStmt = section.Statements.Last();
if (lastStmt is BreakStatementSyntax)
yield return Block(section.Statements.RemoveAt(section.Statements.Count - 1));
else
yield return Block(section.Statements);
}
}
}

[Simplifier]
private IEnumerable<SyntaxNode> SimplifyFor(SyntaxNode node)
{
Expand Down
Loading