private ExpressionSyntax GenIncDec(FuzzType type, bool isIncrement) { SyntaxKind[] acceptedTypes = { SyntaxKind.ULongKeyword, SyntaxKind.LongKeyword, SyntaxKind.UIntKeyword, SyntaxKind.IntKeyword, SyntaxKind.UShortKeyword, SyntaxKind.ShortKeyword, SyntaxKind.ByteKeyword, SyntaxKind.SByteKeyword, }; if (!(type is PrimitiveType pt) || !acceptedTypes.Contains(pt.Keyword)) { return(null); } LValueInfo subject = GenExistingLValue(type, int.MinValue); if (subject == null) { return(null); } ExpressionSyntax gen = PostfixUnaryExpression( isIncrement ? SyntaxKind.PostIncrementExpression : SyntaxKind.PostDecrementExpression, subject.Expression); return(gen); }
/// <summary>Returns an lvalue.</summary> private LValueInfo GenLValue(FuzzType type, int minRefEscapeScope) { Debug.Assert(type != null); LValueInfo lv = GenExistingLValue(type, minRefEscapeScope); if (lv == null) { StaticField newStatic = Statics.GenerateNewField(type); lv = new LValueInfo(IdentifierName(newStatic.Var.Name), type, int.MaxValue); } return(lv); }
private static void AppendVariablePaths(List <LValueInfo> paths, VariableIdentifier var) { ExpressionSyntax varAccess = IdentifierName(var.Name); AddPathsRecursive(varAccess, var.Type, var.RefEscapeScope); void AddPathsRecursive(ExpressionSyntax curAccess, FuzzType curType, int curRefEscapeScope) { LValueInfo info = new LValueInfo(curAccess, curType, curRefEscapeScope); paths.Add(info); if (curType is RefType rt) { curType = rt.InnerType; } switch (curType) { case ArrayType arr: AddPathsRecursive( ElementAccessExpression( curAccess, BracketedArgumentList( SeparatedList( Enumerable.Repeat( Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0))), arr.Rank)))), arr.ElementType, curRefEscapeScope: int.MaxValue); break; case AggregateType agg: foreach (AggregateField field in agg.Fields) { AddPathsRecursive( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, curAccess, IdentifierName(field.Name)), field.Type, curRefEscapeScope: agg.IsClass?int.MaxValue: curRefEscapeScope); } break; } } }
private ArgumentSyntax[] GenArgs(FuncGenerator funcToCall, int minRefEscapeScope, out int argsMinRefEscapeScope) { ArgumentSyntax[] args = new ArgumentSyntax[funcToCall.Parameters.Length]; argsMinRefEscapeScope = int.MaxValue; for (int i = 0; i < args.Length; i++) { FuzzType paramType = funcToCall.Parameters[i].Type; if (paramType is RefType rt) { LValueInfo lv = GenLValue(rt.InnerType, minRefEscapeScope); argsMinRefEscapeScope = Math.Min(argsMinRefEscapeScope, lv.RefEscapeScope); args[i] = Argument(lv.Expression).WithRefKindKeyword(Token(SyntaxKind.RefKeyword)); } else { args[i] = Argument(GenExpression(paramType)); } } return(args); }
private StatementSyntax GenAssignmentStatement() { LValueInfo lvalue = null; if (!Random.FlipCoin(Options.AssignToNewVarProb)) { lvalue = GenExistingLValue(null, int.MinValue); } if (lvalue == null) { FuzzType newType = Types.PickType(Options.LocalIsByRefProb); // Determine if we should create a new local. We do this with a certain probabilty, // or always if the new type is a by-ref type (we cannot have static by-refs). if (newType is RefType || Random.FlipCoin(Options.NewVarIsLocalProb)) { VariableIdentifier variable; string varName = $"var{_varCounter++}"; ExpressionSyntax rhs; if (newType is RefType newRt) { LValueInfo rhsLV = GenLValue(newRt.InnerType, int.MinValue); variable = new VariableIdentifier(newType, varName, rhsLV.RefEscapeScope); rhs = RefExpression(rhsLV.Expression); } else { rhs = GenExpression(newType); variable = new VariableIdentifier(newType, varName, -(_scope.Count - 1)); } LocalDeclarationStatementSyntax decl = LocalDeclarationStatement( VariableDeclaration( variable.Type.GenReferenceTo(), SingletonSeparatedList( VariableDeclarator(variable.Name) .WithInitializer( EqualsValueClause(rhs))))); _scope.Last().Variables.Add(variable); return(decl); } StaticField newStatic = Statics.GenerateNewField(newType); lvalue = new LValueInfo(IdentifierName(newStatic.Var.Name), newType, int.MaxValue); } // Determine if we should generate a ref-reassignment. In that case we cannot do anything // clever, like generate compound assignments. FuzzType rhsType = lvalue.Type; if (lvalue.Type is RefType rt) { if (Random.FlipCoin(Options.AssignGenRefReassignProb)) { RefExpressionSyntax refRhs = RefExpression(GenLValue(rt.InnerType, lvalue.RefEscapeScope).Expression); return (ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, lvalue.Expression, refRhs))); } // We have a ref-type, but are not generating a ref-reassign, so lift the type and make a normal assignment. rhsType = rt.InnerType; } SyntaxKind assignmentKind = SyntaxKind.SimpleAssignmentExpression; // Determine if we should generate compound assignment. if (rhsType.AllowedAdditionalAssignmentKinds.Length > 0 && Random.FlipCoin(Options.CompoundAssignmentProb)) { assignmentKind = Random.NextElement(rhsType.AllowedAdditionalAssignmentKinds); } // Early our for simple cases. if (assignmentKind == SyntaxKind.PreIncrementExpression || assignmentKind == SyntaxKind.PreDecrementExpression) { return(ExpressionStatement(PrefixUnaryExpression(assignmentKind, lvalue.Expression))); } if (assignmentKind == SyntaxKind.PostIncrementExpression || assignmentKind == SyntaxKind.PostDecrementExpression) { return(ExpressionStatement(PostfixUnaryExpression(assignmentKind, lvalue.Expression))); } // Right operand of shifts are always ints. if (assignmentKind == SyntaxKind.LeftShiftAssignmentExpression || assignmentKind == SyntaxKind.RightShiftAssignmentExpression) { rhsType = Types.GetPrimitiveType(SyntaxKind.IntKeyword); } ExpressionSyntax right = GenExpression(rhsType); // For modulo and division we don't want to throw divide-by-zero exceptions, // so always or right-hand-side with 1. if (assignmentKind == SyntaxKind.ModuloAssignmentExpression || assignmentKind == SyntaxKind.DivideAssignmentExpression) { right = CastExpression( rhsType.GenReferenceTo(), ParenthesizedExpression( BinaryExpression( SyntaxKind.BitwiseOrExpression, ParenthesizeIfNecessary(right), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(1))))); } return(ExpressionStatement(AssignmentExpression(assignmentKind, lvalue.Expression, right))); }