1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright 2016, The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include <cmath>
18*795d594fSAndroid Build Coastguard Worker #include <random>
19*795d594fSAndroid Build Coastguard Worker
20*795d594fSAndroid Build Coastguard Worker #include <inttypes.h>
21*795d594fSAndroid Build Coastguard Worker #include <stdio.h>
22*795d594fSAndroid Build Coastguard Worker #include <stdlib.h>
23*795d594fSAndroid Build Coastguard Worker #include <string.h>
24*795d594fSAndroid Build Coastguard Worker #include <unistd.h>
25*795d594fSAndroid Build Coastguard Worker
26*795d594fSAndroid Build Coastguard Worker #include <sys/time.h>
27*795d594fSAndroid Build Coastguard Worker
28*795d594fSAndroid Build Coastguard Worker namespace {
29*795d594fSAndroid Build Coastguard Worker
30*795d594fSAndroid Build Coastguard Worker /*
31*795d594fSAndroid Build Coastguard Worker * Operators.
32*795d594fSAndroid Build Coastguard Worker */
33*795d594fSAndroid Build Coastguard Worker
34*795d594fSAndroid Build Coastguard Worker static constexpr const char* kIncDecOps[] = { "++", "--" };
35*795d594fSAndroid Build Coastguard Worker static constexpr const char* kIntUnaryOps[] = { "+", "-", "~" };
36*795d594fSAndroid Build Coastguard Worker static constexpr const char* kFpUnaryOps[] = { "+", "-" };
37*795d594fSAndroid Build Coastguard Worker
38*795d594fSAndroid Build Coastguard Worker static constexpr const char* kBoolBinOps[] = { "&&", "||", "&", "|", "^" }; // few less common
39*795d594fSAndroid Build Coastguard Worker static constexpr const char* kIntBinOps[] = { "+", "-", "*", "/", "%",
40*795d594fSAndroid Build Coastguard Worker ">>", ">>>", "<<", "&", "|", "^" };
41*795d594fSAndroid Build Coastguard Worker static constexpr const char* kFpBinOps[] = { "+", "-", "*", "/" };
42*795d594fSAndroid Build Coastguard Worker
43*795d594fSAndroid Build Coastguard Worker static constexpr const char* kBoolAssignOps[] = { "=", "&=" , "|=", "^=" }; // few less common
44*795d594fSAndroid Build Coastguard Worker static constexpr const char* kIntAssignOps[] = { "=", "+=", "-=", "*=", "/=", "%=",
45*795d594fSAndroid Build Coastguard Worker ">>=", ">>>=", "<<=", "&=", "|=", "^=" };
46*795d594fSAndroid Build Coastguard Worker static constexpr const char* kFpAssignOps[] = { "=", "+=", "-=", "*=", "/=" };
47*795d594fSAndroid Build Coastguard Worker
48*795d594fSAndroid Build Coastguard Worker static constexpr const char* kBoolRelOps[] = { "==", "!=" };
49*795d594fSAndroid Build Coastguard Worker static constexpr const char* kRelOps[] = { "==", "!=", ">", ">=", "<", "<=" };
50*795d594fSAndroid Build Coastguard Worker
51*795d594fSAndroid Build Coastguard Worker /*
52*795d594fSAndroid Build Coastguard Worker * Exceptions.
53*795d594fSAndroid Build Coastguard Worker */
54*795d594fSAndroid Build Coastguard Worker static const char* kExceptionTypes[] = {
55*795d594fSAndroid Build Coastguard Worker "IllegalStateException",
56*795d594fSAndroid Build Coastguard Worker "NullPointerException",
57*795d594fSAndroid Build Coastguard Worker "IllegalArgumentException",
58*795d594fSAndroid Build Coastguard Worker "ArrayIndexOutOfBoundsException"
59*795d594fSAndroid Build Coastguard Worker };
60*795d594fSAndroid Build Coastguard Worker
61*795d594fSAndroid Build Coastguard Worker /*
62*795d594fSAndroid Build Coastguard Worker * Version of JFuzz. Increase this each time changes are made to the program
63*795d594fSAndroid Build Coastguard Worker * to preserve the property that a given version of JFuzz yields the same
64*795d594fSAndroid Build Coastguard Worker * fuzzed program for a deterministic random seed.
65*795d594fSAndroid Build Coastguard Worker */
66*795d594fSAndroid Build Coastguard Worker const char* VERSION = "1.5";
67*795d594fSAndroid Build Coastguard Worker
68*795d594fSAndroid Build Coastguard Worker /*
69*795d594fSAndroid Build Coastguard Worker * Maximum number of array dimensions, together with corresponding maximum size
70*795d594fSAndroid Build Coastguard Worker * within each dimension (to keep memory/runtime requirements roughly the same).
71*795d594fSAndroid Build Coastguard Worker */
72*795d594fSAndroid Build Coastguard Worker static const uint32_t kMaxDim = 10;
73*795d594fSAndroid Build Coastguard Worker static const uint32_t kMaxDimSize[kMaxDim + 1] = { 0, 1000, 32, 10, 6, 4, 3, 3, 2, 2, 2 };
74*795d594fSAndroid Build Coastguard Worker
75*795d594fSAndroid Build Coastguard Worker /*
76*795d594fSAndroid Build Coastguard Worker * Utility function to return the number of elements in an array.
77*795d594fSAndroid Build Coastguard Worker */
78*795d594fSAndroid Build Coastguard Worker template <typename T, uint32_t N>
countof(T const (&)[N])79*795d594fSAndroid Build Coastguard Worker constexpr uint32_t countof(T const (&)[N]) {
80*795d594fSAndroid Build Coastguard Worker return N;
81*795d594fSAndroid Build Coastguard Worker }
82*795d594fSAndroid Build Coastguard Worker
83*795d594fSAndroid Build Coastguard Worker /**
84*795d594fSAndroid Build Coastguard Worker * A class that generates a random program that compiles correctly. The program
85*795d594fSAndroid Build Coastguard Worker * is generated using rules that generate various programming constructs. Each rule
86*795d594fSAndroid Build Coastguard Worker * has a fixed probability to "fire". Running a generated program yields deterministic
87*795d594fSAndroid Build Coastguard Worker * output, making it suited to test various modes of execution (e.g an interpreter vs.
88*795d594fSAndroid Build Coastguard Worker * an compiler or two different run times) for divergences.
89*795d594fSAndroid Build Coastguard Worker */
90*795d594fSAndroid Build Coastguard Worker class JFuzz {
91*795d594fSAndroid Build Coastguard Worker public:
JFuzz(FILE * out,uint32_t seed,uint32_t expr_depth,uint32_t stmt_length,uint32_t if_nest,uint32_t loop_nest,uint32_t try_nest)92*795d594fSAndroid Build Coastguard Worker JFuzz(FILE* out,
93*795d594fSAndroid Build Coastguard Worker uint32_t seed,
94*795d594fSAndroid Build Coastguard Worker uint32_t expr_depth,
95*795d594fSAndroid Build Coastguard Worker uint32_t stmt_length,
96*795d594fSAndroid Build Coastguard Worker uint32_t if_nest,
97*795d594fSAndroid Build Coastguard Worker uint32_t loop_nest,
98*795d594fSAndroid Build Coastguard Worker uint32_t try_nest)
99*795d594fSAndroid Build Coastguard Worker : out_(out),
100*795d594fSAndroid Build Coastguard Worker fuzz_random_engine_(seed),
101*795d594fSAndroid Build Coastguard Worker fuzz_seed_(seed),
102*795d594fSAndroid Build Coastguard Worker fuzz_expr_depth_(expr_depth),
103*795d594fSAndroid Build Coastguard Worker fuzz_stmt_length_(stmt_length),
104*795d594fSAndroid Build Coastguard Worker fuzz_if_nest_(if_nest),
105*795d594fSAndroid Build Coastguard Worker fuzz_loop_nest_(loop_nest),
106*795d594fSAndroid Build Coastguard Worker fuzz_try_nest_(try_nest),
107*795d594fSAndroid Build Coastguard Worker return_type_(randomType()),
108*795d594fSAndroid Build Coastguard Worker array_type_(randomType()),
109*795d594fSAndroid Build Coastguard Worker array_dim_(random1(kMaxDim)),
110*795d594fSAndroid Build Coastguard Worker array_size_(random1(kMaxDimSize[array_dim_])),
111*795d594fSAndroid Build Coastguard Worker indentation_(0),
112*795d594fSAndroid Build Coastguard Worker expr_depth_(0),
113*795d594fSAndroid Build Coastguard Worker stmt_length_(0),
114*795d594fSAndroid Build Coastguard Worker if_nest_(0),
115*795d594fSAndroid Build Coastguard Worker loop_nest_(0),
116*795d594fSAndroid Build Coastguard Worker switch_nest_(0),
117*795d594fSAndroid Build Coastguard Worker do_nest_(0),
118*795d594fSAndroid Build Coastguard Worker try_nest_(0),
119*795d594fSAndroid Build Coastguard Worker boolean_local_(0),
120*795d594fSAndroid Build Coastguard Worker int_local_(0),
121*795d594fSAndroid Build Coastguard Worker long_local_(0),
122*795d594fSAndroid Build Coastguard Worker float_local_(0),
123*795d594fSAndroid Build Coastguard Worker double_local_(0),
124*795d594fSAndroid Build Coastguard Worker in_inner_(false) { }
125*795d594fSAndroid Build Coastguard Worker
~JFuzz()126*795d594fSAndroid Build Coastguard Worker ~JFuzz() { }
127*795d594fSAndroid Build Coastguard Worker
emitProgram()128*795d594fSAndroid Build Coastguard Worker void emitProgram() {
129*795d594fSAndroid Build Coastguard Worker emitHeader();
130*795d594fSAndroid Build Coastguard Worker emitTestClassWithMain();
131*795d594fSAndroid Build Coastguard Worker }
132*795d594fSAndroid Build Coastguard Worker
133*795d594fSAndroid Build Coastguard Worker private:
134*795d594fSAndroid Build Coastguard Worker //
135*795d594fSAndroid Build Coastguard Worker // Types.
136*795d594fSAndroid Build Coastguard Worker //
137*795d594fSAndroid Build Coastguard Worker
138*795d594fSAndroid Build Coastguard Worker // Current type of each expression during generation.
139*795d594fSAndroid Build Coastguard Worker enum Type {
140*795d594fSAndroid Build Coastguard Worker kBoolean,
141*795d594fSAndroid Build Coastguard Worker kInt,
142*795d594fSAndroid Build Coastguard Worker kLong,
143*795d594fSAndroid Build Coastguard Worker kFloat,
144*795d594fSAndroid Build Coastguard Worker kDouble
145*795d594fSAndroid Build Coastguard Worker };
146*795d594fSAndroid Build Coastguard Worker
147*795d594fSAndroid Build Coastguard Worker // Test for an integral type.
isInteger(Type tp)148*795d594fSAndroid Build Coastguard Worker static bool isInteger(Type tp) {
149*795d594fSAndroid Build Coastguard Worker return tp == kInt || tp == kLong;
150*795d594fSAndroid Build Coastguard Worker }
151*795d594fSAndroid Build Coastguard Worker
152*795d594fSAndroid Build Coastguard Worker // Test for a floating-point type.
isFP(Type tp)153*795d594fSAndroid Build Coastguard Worker static bool isFP(Type tp) {
154*795d594fSAndroid Build Coastguard Worker return tp == kFloat || tp == kDouble;
155*795d594fSAndroid Build Coastguard Worker }
156*795d594fSAndroid Build Coastguard Worker
157*795d594fSAndroid Build Coastguard Worker // Emit type.
emitType(Type tp) const158*795d594fSAndroid Build Coastguard Worker void emitType(Type tp) const {
159*795d594fSAndroid Build Coastguard Worker switch (tp) {
160*795d594fSAndroid Build Coastguard Worker case kBoolean: fputs("boolean", out_); break;
161*795d594fSAndroid Build Coastguard Worker case kInt: fputs("int", out_); break;
162*795d594fSAndroid Build Coastguard Worker case kLong: fputs("long", out_); break;
163*795d594fSAndroid Build Coastguard Worker case kFloat: fputs("float", out_); break;
164*795d594fSAndroid Build Coastguard Worker case kDouble: fputs("double", out_); break;
165*795d594fSAndroid Build Coastguard Worker }
166*795d594fSAndroid Build Coastguard Worker }
167*795d594fSAndroid Build Coastguard Worker
168*795d594fSAndroid Build Coastguard Worker // Emit type class.
emitTypeClass(Type tp) const169*795d594fSAndroid Build Coastguard Worker void emitTypeClass(Type tp) const {
170*795d594fSAndroid Build Coastguard Worker switch (tp) {
171*795d594fSAndroid Build Coastguard Worker case kBoolean: fputs("Boolean", out_); break;
172*795d594fSAndroid Build Coastguard Worker case kInt: fputs("Integer", out_); break;
173*795d594fSAndroid Build Coastguard Worker case kLong: fputs("Long", out_); break;
174*795d594fSAndroid Build Coastguard Worker case kFloat: fputs("Float", out_); break;
175*795d594fSAndroid Build Coastguard Worker case kDouble: fputs("Double", out_); break;
176*795d594fSAndroid Build Coastguard Worker }
177*795d594fSAndroid Build Coastguard Worker }
178*795d594fSAndroid Build Coastguard Worker
179*795d594fSAndroid Build Coastguard Worker // Return a random type.
randomType()180*795d594fSAndroid Build Coastguard Worker Type randomType() {
181*795d594fSAndroid Build Coastguard Worker switch (random1(5)) {
182*795d594fSAndroid Build Coastguard Worker case 1: return kBoolean;
183*795d594fSAndroid Build Coastguard Worker case 2: return kInt;
184*795d594fSAndroid Build Coastguard Worker case 3: return kLong;
185*795d594fSAndroid Build Coastguard Worker case 4: return kFloat;
186*795d594fSAndroid Build Coastguard Worker default: return kDouble;
187*795d594fSAndroid Build Coastguard Worker }
188*795d594fSAndroid Build Coastguard Worker }
189*795d594fSAndroid Build Coastguard Worker
190*795d594fSAndroid Build Coastguard Worker // Emits a random strong selected from an array of operator strings.
191*795d594fSAndroid Build Coastguard Worker template <std::uint32_t N>
emitOneOf(const char * const (& ops)[N])192*795d594fSAndroid Build Coastguard Worker inline void emitOneOf(const char* const (&ops)[N]) {
193*795d594fSAndroid Build Coastguard Worker fputs(ops[random0(N)], out_);
194*795d594fSAndroid Build Coastguard Worker }
195*795d594fSAndroid Build Coastguard Worker
196*795d594fSAndroid Build Coastguard Worker //
197*795d594fSAndroid Build Coastguard Worker // Expressions.
198*795d594fSAndroid Build Coastguard Worker //
199*795d594fSAndroid Build Coastguard Worker
200*795d594fSAndroid Build Coastguard Worker // Emit an unary operator (same type in-out).
emitUnaryOp(Type tp)201*795d594fSAndroid Build Coastguard Worker void emitUnaryOp(Type tp) {
202*795d594fSAndroid Build Coastguard Worker if (tp == kBoolean) {
203*795d594fSAndroid Build Coastguard Worker fputc('!', out_);
204*795d594fSAndroid Build Coastguard Worker } else if (isInteger(tp)) {
205*795d594fSAndroid Build Coastguard Worker emitOneOf(kIntUnaryOps);
206*795d594fSAndroid Build Coastguard Worker } else { // isFP(tp)
207*795d594fSAndroid Build Coastguard Worker emitOneOf(kFpUnaryOps);
208*795d594fSAndroid Build Coastguard Worker }
209*795d594fSAndroid Build Coastguard Worker }
210*795d594fSAndroid Build Coastguard Worker
211*795d594fSAndroid Build Coastguard Worker // Emit a pre/post-increment/decrement operator (same type in-out).
emitIncDecOp(Type tp)212*795d594fSAndroid Build Coastguard Worker void emitIncDecOp(Type tp) {
213*795d594fSAndroid Build Coastguard Worker if (tp == kBoolean) {
214*795d594fSAndroid Build Coastguard Worker // Not applicable, just leave "as is".
215*795d594fSAndroid Build Coastguard Worker } else { // isInteger(tp) || isFP(tp)
216*795d594fSAndroid Build Coastguard Worker emitOneOf(kIncDecOps);
217*795d594fSAndroid Build Coastguard Worker }
218*795d594fSAndroid Build Coastguard Worker }
219*795d594fSAndroid Build Coastguard Worker
220*795d594fSAndroid Build Coastguard Worker // Emit a binary operator (same type in-out).
emitBinaryOp(Type tp)221*795d594fSAndroid Build Coastguard Worker void emitBinaryOp(Type tp) {
222*795d594fSAndroid Build Coastguard Worker if (tp == kBoolean) {
223*795d594fSAndroid Build Coastguard Worker emitOneOf(kBoolBinOps);
224*795d594fSAndroid Build Coastguard Worker } else if (isInteger(tp)) {
225*795d594fSAndroid Build Coastguard Worker emitOneOf(kIntBinOps);
226*795d594fSAndroid Build Coastguard Worker } else { // isFP(tp)
227*795d594fSAndroid Build Coastguard Worker emitOneOf(kFpBinOps);
228*795d594fSAndroid Build Coastguard Worker }
229*795d594fSAndroid Build Coastguard Worker }
230*795d594fSAndroid Build Coastguard Worker
231*795d594fSAndroid Build Coastguard Worker // Emit an assignment operator (same type in-out).
emitAssignmentOp(Type tp)232*795d594fSAndroid Build Coastguard Worker void emitAssignmentOp(Type tp) {
233*795d594fSAndroid Build Coastguard Worker if (tp == kBoolean) {
234*795d594fSAndroid Build Coastguard Worker emitOneOf(kBoolAssignOps);
235*795d594fSAndroid Build Coastguard Worker } else if (isInteger(tp)) {
236*795d594fSAndroid Build Coastguard Worker emitOneOf(kIntAssignOps);
237*795d594fSAndroid Build Coastguard Worker } else { // isFP(tp)
238*795d594fSAndroid Build Coastguard Worker emitOneOf(kFpAssignOps);
239*795d594fSAndroid Build Coastguard Worker }
240*795d594fSAndroid Build Coastguard Worker }
241*795d594fSAndroid Build Coastguard Worker
242*795d594fSAndroid Build Coastguard Worker // Emit a relational operator (one type in, boolean out).
emitRelationalOp(Type tp)243*795d594fSAndroid Build Coastguard Worker void emitRelationalOp(Type tp) {
244*795d594fSAndroid Build Coastguard Worker if (tp == kBoolean) {
245*795d594fSAndroid Build Coastguard Worker emitOneOf(kBoolRelOps);
246*795d594fSAndroid Build Coastguard Worker } else { // isInteger(tp) || isFP(tp)
247*795d594fSAndroid Build Coastguard Worker emitOneOf(kRelOps);
248*795d594fSAndroid Build Coastguard Worker }
249*795d594fSAndroid Build Coastguard Worker }
250*795d594fSAndroid Build Coastguard Worker
251*795d594fSAndroid Build Coastguard Worker // Emit a type conversion operator sequence (out type given, new suitable in type picked).
emitTypeConversionOp(Type tp)252*795d594fSAndroid Build Coastguard Worker Type emitTypeConversionOp(Type tp) {
253*795d594fSAndroid Build Coastguard Worker if (tp == kInt) {
254*795d594fSAndroid Build Coastguard Worker switch (random1(5)) {
255*795d594fSAndroid Build Coastguard Worker case 1: fputs("(int)", out_); return kLong;
256*795d594fSAndroid Build Coastguard Worker case 2: fputs("(int)", out_); return kFloat;
257*795d594fSAndroid Build Coastguard Worker case 3: fputs("(int)", out_); return kDouble;
258*795d594fSAndroid Build Coastguard Worker // Narrowing-widening.
259*795d594fSAndroid Build Coastguard Worker case 4: fputs("(int)(byte)(int)", out_); return kInt;
260*795d594fSAndroid Build Coastguard Worker case 5: fputs("(int)(short)(int)", out_); return kInt;
261*795d594fSAndroid Build Coastguard Worker }
262*795d594fSAndroid Build Coastguard Worker } else if (tp == kLong) {
263*795d594fSAndroid Build Coastguard Worker switch (random1(6)) {
264*795d594fSAndroid Build Coastguard Worker case 1: /* implicit */ return kInt;
265*795d594fSAndroid Build Coastguard Worker case 2: fputs("(long)", out_); return kFloat;
266*795d594fSAndroid Build Coastguard Worker case 3: fputs("(long)", out_); return kDouble;
267*795d594fSAndroid Build Coastguard Worker // Narrowing-widening.
268*795d594fSAndroid Build Coastguard Worker case 4: fputs("(long)(byte)(long)", out_); return kLong;
269*795d594fSAndroid Build Coastguard Worker case 5: fputs("(long)(short)(long)", out_); return kLong;
270*795d594fSAndroid Build Coastguard Worker case 6: fputs("(long)(int)(long)", out_); return kLong;
271*795d594fSAndroid Build Coastguard Worker }
272*795d594fSAndroid Build Coastguard Worker } else if (tp == kFloat) {
273*795d594fSAndroid Build Coastguard Worker switch (random1(4)) {
274*795d594fSAndroid Build Coastguard Worker case 1: fputs("(float)", out_); return kInt;
275*795d594fSAndroid Build Coastguard Worker case 2: fputs("(float)", out_); return kLong;
276*795d594fSAndroid Build Coastguard Worker case 3: fputs("(float)", out_); return kDouble;
277*795d594fSAndroid Build Coastguard Worker // Narrowing-widening.
278*795d594fSAndroid Build Coastguard Worker case 4: fputs("(float)(int)(float)", out_); return kFloat;
279*795d594fSAndroid Build Coastguard Worker }
280*795d594fSAndroid Build Coastguard Worker } else if (tp == kDouble) {
281*795d594fSAndroid Build Coastguard Worker switch (random1(5)) {
282*795d594fSAndroid Build Coastguard Worker case 1: fputs("(double)", out_); return kInt;
283*795d594fSAndroid Build Coastguard Worker case 2: fputs("(double)", out_); return kLong;
284*795d594fSAndroid Build Coastguard Worker case 3: fputs("(double)", out_); return kFloat;
285*795d594fSAndroid Build Coastguard Worker // Narrowing-widening.
286*795d594fSAndroid Build Coastguard Worker case 4: fputs("(double)(int)(double)", out_); return kDouble;
287*795d594fSAndroid Build Coastguard Worker case 5: fputs("(double)(float)(double)", out_); return kDouble;
288*795d594fSAndroid Build Coastguard Worker }
289*795d594fSAndroid Build Coastguard Worker }
290*795d594fSAndroid Build Coastguard Worker return tp; // nothing suitable, just keep type
291*795d594fSAndroid Build Coastguard Worker }
292*795d594fSAndroid Build Coastguard Worker
293*795d594fSAndroid Build Coastguard Worker // Emit a type conversion (out type given, new suitable in type picked).
emitTypeConversion(Type tp)294*795d594fSAndroid Build Coastguard Worker void emitTypeConversion(Type tp) {
295*795d594fSAndroid Build Coastguard Worker if (tp == kBoolean) {
296*795d594fSAndroid Build Coastguard Worker Type tp = randomType();
297*795d594fSAndroid Build Coastguard Worker emitExpression(tp);
298*795d594fSAndroid Build Coastguard Worker fputc(' ', out_);
299*795d594fSAndroid Build Coastguard Worker emitRelationalOp(tp);
300*795d594fSAndroid Build Coastguard Worker fputc(' ', out_);
301*795d594fSAndroid Build Coastguard Worker emitExpression(tp);
302*795d594fSAndroid Build Coastguard Worker } else {
303*795d594fSAndroid Build Coastguard Worker tp = emitTypeConversionOp(tp);
304*795d594fSAndroid Build Coastguard Worker fputc(' ', out_);
305*795d594fSAndroid Build Coastguard Worker emitExpression(tp);
306*795d594fSAndroid Build Coastguard Worker }
307*795d594fSAndroid Build Coastguard Worker }
308*795d594fSAndroid Build Coastguard Worker
309*795d594fSAndroid Build Coastguard Worker // Emit an unary intrinsic (out type given, new suitable in type picked).
emitIntrinsic1(Type tp)310*795d594fSAndroid Build Coastguard Worker Type emitIntrinsic1(Type tp) {
311*795d594fSAndroid Build Coastguard Worker if (tp == kBoolean) {
312*795d594fSAndroid Build Coastguard Worker switch (random1(6)) {
313*795d594fSAndroid Build Coastguard Worker case 1: fputs("Float.isNaN", out_); return kFloat;
314*795d594fSAndroid Build Coastguard Worker case 2: fputs("Float.isFinite", out_); return kFloat;
315*795d594fSAndroid Build Coastguard Worker case 3: fputs("Float.isInfinite", out_); return kFloat;
316*795d594fSAndroid Build Coastguard Worker case 4: fputs("Double.isNaN", out_); return kDouble;
317*795d594fSAndroid Build Coastguard Worker case 5: fputs("Double.isFinite", out_); return kDouble;
318*795d594fSAndroid Build Coastguard Worker case 6: fputs("Double.isInfinite", out_); return kDouble;
319*795d594fSAndroid Build Coastguard Worker }
320*795d594fSAndroid Build Coastguard Worker } else if (isInteger(tp)) {
321*795d594fSAndroid Build Coastguard Worker const char* prefix = tp == kLong ? "Long" : "Integer";
322*795d594fSAndroid Build Coastguard Worker switch (random1(13)) {
323*795d594fSAndroid Build Coastguard Worker case 1: fprintf(out_, "%s.highestOneBit", prefix); break;
324*795d594fSAndroid Build Coastguard Worker case 2: fprintf(out_, "%s.lowestOneBit", prefix); break;
325*795d594fSAndroid Build Coastguard Worker case 3: fprintf(out_, "%s.numberOfLeadingZeros", prefix); break;
326*795d594fSAndroid Build Coastguard Worker case 4: fprintf(out_, "%s.numberOfTrailingZeros", prefix); break;
327*795d594fSAndroid Build Coastguard Worker case 5: fprintf(out_, "%s.bitCount", prefix); break;
328*795d594fSAndroid Build Coastguard Worker case 6: fprintf(out_, "%s.signum", prefix); break;
329*795d594fSAndroid Build Coastguard Worker case 7: fprintf(out_, "%s.reverse", prefix); break;
330*795d594fSAndroid Build Coastguard Worker case 8: fprintf(out_, "%s.reverseBytes", prefix); break;
331*795d594fSAndroid Build Coastguard Worker case 9: fputs("Math.incrementExact", out_); break;
332*795d594fSAndroid Build Coastguard Worker case 10: fputs("Math.decrementExact", out_); break;
333*795d594fSAndroid Build Coastguard Worker case 11: fputs("Math.negateExact", out_); break;
334*795d594fSAndroid Build Coastguard Worker case 12: fputs("Math.abs", out_); break;
335*795d594fSAndroid Build Coastguard Worker case 13: fputs("Math.round", out_);
336*795d594fSAndroid Build Coastguard Worker return tp == kLong ? kDouble : kFloat;
337*795d594fSAndroid Build Coastguard Worker }
338*795d594fSAndroid Build Coastguard Worker } else { // isFP(tp)
339*795d594fSAndroid Build Coastguard Worker switch (random1(6)) {
340*795d594fSAndroid Build Coastguard Worker case 1: fputs("Math.abs", out_); break;
341*795d594fSAndroid Build Coastguard Worker case 2: fputs("Math.ulp", out_); break;
342*795d594fSAndroid Build Coastguard Worker case 3: fputs("Math.signum", out_); break;
343*795d594fSAndroid Build Coastguard Worker case 4: fputs("Math.nextUp", out_); break;
344*795d594fSAndroid Build Coastguard Worker case 5: fputs("Math.nextDown", out_); break;
345*795d594fSAndroid Build Coastguard Worker case 6: if (tp == kDouble) {
346*795d594fSAndroid Build Coastguard Worker fputs("Double.longBitsToDouble", out_);
347*795d594fSAndroid Build Coastguard Worker return kLong;
348*795d594fSAndroid Build Coastguard Worker } else {
349*795d594fSAndroid Build Coastguard Worker fputs("Float.intBitsToFloat", out_);
350*795d594fSAndroid Build Coastguard Worker return kInt;
351*795d594fSAndroid Build Coastguard Worker }
352*795d594fSAndroid Build Coastguard Worker }
353*795d594fSAndroid Build Coastguard Worker }
354*795d594fSAndroid Build Coastguard Worker return tp; // same type in-out
355*795d594fSAndroid Build Coastguard Worker }
356*795d594fSAndroid Build Coastguard Worker
357*795d594fSAndroid Build Coastguard Worker // Emit a binary intrinsic (out type given, new suitable in type picked).
emitIntrinsic2(Type tp)358*795d594fSAndroid Build Coastguard Worker Type emitIntrinsic2(Type tp) {
359*795d594fSAndroid Build Coastguard Worker if (tp == kBoolean) {
360*795d594fSAndroid Build Coastguard Worker switch (random1(3)) {
361*795d594fSAndroid Build Coastguard Worker case 1: fputs("Boolean.logicalAnd", out_); break;
362*795d594fSAndroid Build Coastguard Worker case 2: fputs("Boolean.logicalOr", out_); break;
363*795d594fSAndroid Build Coastguard Worker case 3: fputs("Boolean.logicalXor", out_); break;
364*795d594fSAndroid Build Coastguard Worker }
365*795d594fSAndroid Build Coastguard Worker } else if (isInteger(tp)) {
366*795d594fSAndroid Build Coastguard Worker const char* prefix = tp == kLong ? "Long" : "Integer";
367*795d594fSAndroid Build Coastguard Worker switch (random1(11)) {
368*795d594fSAndroid Build Coastguard Worker case 1: fprintf(out_, "%s.compare", prefix); break;
369*795d594fSAndroid Build Coastguard Worker case 2: fprintf(out_, "%s.sum", prefix); break;
370*795d594fSAndroid Build Coastguard Worker case 3: fprintf(out_, "%s.min", prefix); break;
371*795d594fSAndroid Build Coastguard Worker case 4: fprintf(out_, "%s.max", prefix); break;
372*795d594fSAndroid Build Coastguard Worker case 5: fputs("Math.min", out_); break;
373*795d594fSAndroid Build Coastguard Worker case 6: fputs("Math.max", out_); break;
374*795d594fSAndroid Build Coastguard Worker case 7: fputs("Math.floorDiv", out_); break;
375*795d594fSAndroid Build Coastguard Worker case 8: fputs("Math.floorMod", out_); break;
376*795d594fSAndroid Build Coastguard Worker case 9: fputs("Math.addExact", out_); break;
377*795d594fSAndroid Build Coastguard Worker case 10: fputs("Math.subtractExact", out_); break;
378*795d594fSAndroid Build Coastguard Worker case 11: fputs("Math.multiplyExact", out_); break;
379*795d594fSAndroid Build Coastguard Worker }
380*795d594fSAndroid Build Coastguard Worker } else { // isFP(tp)
381*795d594fSAndroid Build Coastguard Worker const char* prefix = tp == kDouble ? "Double" : "Float";
382*795d594fSAndroid Build Coastguard Worker switch (random1(5)) {
383*795d594fSAndroid Build Coastguard Worker case 1: fprintf(out_, "%s.sum", prefix); break;
384*795d594fSAndroid Build Coastguard Worker case 2: fprintf(out_, "%s.min", prefix); break;
385*795d594fSAndroid Build Coastguard Worker case 3: fprintf(out_, "%s.max", prefix); break;
386*795d594fSAndroid Build Coastguard Worker case 4: fputs("Math.min", out_); break;
387*795d594fSAndroid Build Coastguard Worker case 5: fputs("Math.max", out_); break;
388*795d594fSAndroid Build Coastguard Worker }
389*795d594fSAndroid Build Coastguard Worker }
390*795d594fSAndroid Build Coastguard Worker return tp; // same type in-out
391*795d594fSAndroid Build Coastguard Worker }
392*795d594fSAndroid Build Coastguard Worker
393*795d594fSAndroid Build Coastguard Worker // Emit an intrinsic (out type given, new suitable in type picked).
emitIntrinsic(Type tp)394*795d594fSAndroid Build Coastguard Worker void emitIntrinsic(Type tp) {
395*795d594fSAndroid Build Coastguard Worker if (random1(2) == 1) {
396*795d594fSAndroid Build Coastguard Worker tp = emitIntrinsic1(tp);
397*795d594fSAndroid Build Coastguard Worker fputc('(', out_);
398*795d594fSAndroid Build Coastguard Worker emitExpression(tp);
399*795d594fSAndroid Build Coastguard Worker fputc(')', out_);
400*795d594fSAndroid Build Coastguard Worker } else {
401*795d594fSAndroid Build Coastguard Worker tp = emitIntrinsic2(tp);
402*795d594fSAndroid Build Coastguard Worker fputc('(', out_);
403*795d594fSAndroid Build Coastguard Worker emitExpression(tp);
404*795d594fSAndroid Build Coastguard Worker fputs(", ", out_);
405*795d594fSAndroid Build Coastguard Worker emitExpression(tp);
406*795d594fSAndroid Build Coastguard Worker fputc(')', out_);
407*795d594fSAndroid Build Coastguard Worker }
408*795d594fSAndroid Build Coastguard Worker }
409*795d594fSAndroid Build Coastguard Worker
410*795d594fSAndroid Build Coastguard Worker // Emit a method call (out type given).
emitMethodCall(Type tp)411*795d594fSAndroid Build Coastguard Worker void emitMethodCall(Type tp) {
412*795d594fSAndroid Build Coastguard Worker if (tp != kBoolean && !in_inner_) {
413*795d594fSAndroid Build Coastguard Worker // Accept all numerical types (implicit conversion) and when not
414*795d594fSAndroid Build Coastguard Worker // declaring inner classes (to avoid infinite recursion).
415*795d594fSAndroid Build Coastguard Worker switch (random1(8)) {
416*795d594fSAndroid Build Coastguard Worker case 1: fputs("mA.a()", out_); break;
417*795d594fSAndroid Build Coastguard Worker case 2: fputs("mB.a()", out_); break;
418*795d594fSAndroid Build Coastguard Worker case 3: fputs("mB.x()", out_); break;
419*795d594fSAndroid Build Coastguard Worker case 4: fputs("mBX.x()", out_); break;
420*795d594fSAndroid Build Coastguard Worker case 5: fputs("mC.s()", out_); break;
421*795d594fSAndroid Build Coastguard Worker case 6: fputs("mC.c()", out_); break;
422*795d594fSAndroid Build Coastguard Worker case 7: fputs("mC.x()", out_); break;
423*795d594fSAndroid Build Coastguard Worker case 8: fputs("mCX.x()", out_); break;
424*795d594fSAndroid Build Coastguard Worker }
425*795d594fSAndroid Build Coastguard Worker } else {
426*795d594fSAndroid Build Coastguard Worker // Fall back to intrinsic.
427*795d594fSAndroid Build Coastguard Worker emitIntrinsic(tp);
428*795d594fSAndroid Build Coastguard Worker }
429*795d594fSAndroid Build Coastguard Worker }
430*795d594fSAndroid Build Coastguard Worker
431*795d594fSAndroid Build Coastguard Worker // Emit unboxing boxed object.
emitUnbox(Type tp)432*795d594fSAndroid Build Coastguard Worker void emitUnbox(Type tp) {
433*795d594fSAndroid Build Coastguard Worker fputc('(', out_);
434*795d594fSAndroid Build Coastguard Worker emitType(tp);
435*795d594fSAndroid Build Coastguard Worker fputs(") new ", out_);
436*795d594fSAndroid Build Coastguard Worker emitTypeClass(tp);
437*795d594fSAndroid Build Coastguard Worker fputc('(', out_);
438*795d594fSAndroid Build Coastguard Worker emitExpression(tp);
439*795d594fSAndroid Build Coastguard Worker fputc(')', out_);
440*795d594fSAndroid Build Coastguard Worker }
441*795d594fSAndroid Build Coastguard Worker
442*795d594fSAndroid Build Coastguard Worker // Emit miscellaneous constructs.
emitMisc(Type tp)443*795d594fSAndroid Build Coastguard Worker void emitMisc(Type tp) {
444*795d594fSAndroid Build Coastguard Worker if (tp == kBoolean) {
445*795d594fSAndroid Build Coastguard Worker fprintf(out_, "this instanceof %s", in_inner_ ? "X" : "Test");
446*795d594fSAndroid Build Coastguard Worker } else if (isInteger(tp)) {
447*795d594fSAndroid Build Coastguard Worker const char* prefix = tp == kLong ? "Long" : "Integer";
448*795d594fSAndroid Build Coastguard Worker switch (random1(2)) {
449*795d594fSAndroid Build Coastguard Worker case 1: fprintf(out_, "%s.MIN_VALUE", prefix); break;
450*795d594fSAndroid Build Coastguard Worker case 2: fprintf(out_, "%s.MAX_VALUE", prefix); break;
451*795d594fSAndroid Build Coastguard Worker }
452*795d594fSAndroid Build Coastguard Worker } else { // isFP(tp)
453*795d594fSAndroid Build Coastguard Worker const char* prefix = tp == kDouble ? "Double" : "Float";
454*795d594fSAndroid Build Coastguard Worker switch (random1(6)) {
455*795d594fSAndroid Build Coastguard Worker case 1: fprintf(out_, "%s.MIN_NORMAL", prefix); break;
456*795d594fSAndroid Build Coastguard Worker case 2: fprintf(out_, "%s.MIN_VALUE", prefix); break;
457*795d594fSAndroid Build Coastguard Worker case 3: fprintf(out_, "%s.MAX_VALUE", prefix); break;
458*795d594fSAndroid Build Coastguard Worker case 4: fprintf(out_, "%s.POSITIVE_INFINITY", prefix); break;
459*795d594fSAndroid Build Coastguard Worker case 5: fprintf(out_, "%s.NEGATIVE_INFINITY", prefix); break;
460*795d594fSAndroid Build Coastguard Worker case 6: fprintf(out_, "%s.NaN", prefix); break;
461*795d594fSAndroid Build Coastguard Worker }
462*795d594fSAndroid Build Coastguard Worker }
463*795d594fSAndroid Build Coastguard Worker }
464*795d594fSAndroid Build Coastguard Worker
465*795d594fSAndroid Build Coastguard Worker // Adjust local of given type and return adjusted value.
adjustLocal(Type tp,int32_t a)466*795d594fSAndroid Build Coastguard Worker uint32_t adjustLocal(Type tp, int32_t a) {
467*795d594fSAndroid Build Coastguard Worker switch (tp) {
468*795d594fSAndroid Build Coastguard Worker case kBoolean: boolean_local_ += a; return boolean_local_;
469*795d594fSAndroid Build Coastguard Worker case kInt: int_local_ += a; return int_local_;
470*795d594fSAndroid Build Coastguard Worker case kLong: long_local_ += a; return long_local_;
471*795d594fSAndroid Build Coastguard Worker case kFloat: float_local_ += a; return float_local_;
472*795d594fSAndroid Build Coastguard Worker default: double_local_ += a; return double_local_;
473*795d594fSAndroid Build Coastguard Worker }
474*795d594fSAndroid Build Coastguard Worker }
475*795d594fSAndroid Build Coastguard Worker
476*795d594fSAndroid Build Coastguard Worker // Emit an expression that is a strict upper bound for an array index.
emitUpperBound()477*795d594fSAndroid Build Coastguard Worker void emitUpperBound() {
478*795d594fSAndroid Build Coastguard Worker if (random1(8) == 1) {
479*795d594fSAndroid Build Coastguard Worker fputs("mArray.length", out_);
480*795d594fSAndroid Build Coastguard Worker } else if (random1(8) == 1) {
481*795d594fSAndroid Build Coastguard Worker fprintf(out_, "%u", random1(array_size_)); // random in range
482*795d594fSAndroid Build Coastguard Worker } else {
483*795d594fSAndroid Build Coastguard Worker fprintf(out_, "%u", array_size_);
484*795d594fSAndroid Build Coastguard Worker }
485*795d594fSAndroid Build Coastguard Worker }
486*795d594fSAndroid Build Coastguard Worker
487*795d594fSAndroid Build Coastguard Worker // Emit an array index, usually within proper range.
emitArrayIndex()488*795d594fSAndroid Build Coastguard Worker void emitArrayIndex() {
489*795d594fSAndroid Build Coastguard Worker if (loop_nest_ > 0 && random1(2) == 1) {
490*795d594fSAndroid Build Coastguard Worker fprintf(out_, "i%u", random0(loop_nest_));
491*795d594fSAndroid Build Coastguard Worker } else if (random1(8) == 1) {
492*795d594fSAndroid Build Coastguard Worker fputs("mArray.length - 1", out_);
493*795d594fSAndroid Build Coastguard Worker } else {
494*795d594fSAndroid Build Coastguard Worker fprintf(out_, "%u", random0(array_size_)); // random in range
495*795d594fSAndroid Build Coastguard Worker }
496*795d594fSAndroid Build Coastguard Worker // Introduce potential off by one errors with low probability.
497*795d594fSAndroid Build Coastguard Worker if (random1(100) == 1) {
498*795d594fSAndroid Build Coastguard Worker if (random1(2) == 1) {
499*795d594fSAndroid Build Coastguard Worker fputs(" - 1", out_);
500*795d594fSAndroid Build Coastguard Worker } else {
501*795d594fSAndroid Build Coastguard Worker fputs(" + 1", out_);
502*795d594fSAndroid Build Coastguard Worker }
503*795d594fSAndroid Build Coastguard Worker }
504*795d594fSAndroid Build Coastguard Worker }
505*795d594fSAndroid Build Coastguard Worker
506*795d594fSAndroid Build Coastguard Worker // Emit a literal.
emitLiteral(Type tp)507*795d594fSAndroid Build Coastguard Worker void emitLiteral(Type tp) {
508*795d594fSAndroid Build Coastguard Worker switch (tp) {
509*795d594fSAndroid Build Coastguard Worker case kBoolean: fputs(random1(2) == 1 ? "true" : "false", out_); break;
510*795d594fSAndroid Build Coastguard Worker case kInt: fprintf(out_, "%d", random()); break;
511*795d594fSAndroid Build Coastguard Worker case kLong: fprintf(out_, "%dL", random()); break;
512*795d594fSAndroid Build Coastguard Worker case kFloat: fprintf(out_, "%d.0f", random()); break;
513*795d594fSAndroid Build Coastguard Worker case kDouble: fprintf(out_, "%d.0", random()); break;
514*795d594fSAndroid Build Coastguard Worker }
515*795d594fSAndroid Build Coastguard Worker }
516*795d594fSAndroid Build Coastguard Worker
517*795d594fSAndroid Build Coastguard Worker // Emit array variable, if available.
emitArrayVariable(Type tp)518*795d594fSAndroid Build Coastguard Worker bool emitArrayVariable(Type tp) {
519*795d594fSAndroid Build Coastguard Worker if (tp == array_type_) {
520*795d594fSAndroid Build Coastguard Worker fputs("mArray", out_);
521*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < array_dim_; i++) {
522*795d594fSAndroid Build Coastguard Worker fputc('[', out_);
523*795d594fSAndroid Build Coastguard Worker emitArrayIndex();
524*795d594fSAndroid Build Coastguard Worker fputc(']', out_);
525*795d594fSAndroid Build Coastguard Worker }
526*795d594fSAndroid Build Coastguard Worker return true;
527*795d594fSAndroid Build Coastguard Worker }
528*795d594fSAndroid Build Coastguard Worker return false;
529*795d594fSAndroid Build Coastguard Worker }
530*795d594fSAndroid Build Coastguard Worker
531*795d594fSAndroid Build Coastguard Worker // Emit a local variable, if available.
emitLocalVariable(Type tp)532*795d594fSAndroid Build Coastguard Worker bool emitLocalVariable(Type tp) {
533*795d594fSAndroid Build Coastguard Worker uint32_t locals = adjustLocal(tp, 0);
534*795d594fSAndroid Build Coastguard Worker if (locals > 0) {
535*795d594fSAndroid Build Coastguard Worker uint32_t local = random0(locals);
536*795d594fSAndroid Build Coastguard Worker switch (tp) {
537*795d594fSAndroid Build Coastguard Worker case kBoolean: fprintf(out_, "lZ%u", local); break;
538*795d594fSAndroid Build Coastguard Worker case kInt: fprintf(out_, "lI%u", local); break;
539*795d594fSAndroid Build Coastguard Worker case kLong: fprintf(out_, "lJ%u", local); break;
540*795d594fSAndroid Build Coastguard Worker case kFloat: fprintf(out_, "lF%u", local); break;
541*795d594fSAndroid Build Coastguard Worker case kDouble: fprintf(out_, "lD%u", local); break;
542*795d594fSAndroid Build Coastguard Worker }
543*795d594fSAndroid Build Coastguard Worker return true;
544*795d594fSAndroid Build Coastguard Worker }
545*795d594fSAndroid Build Coastguard Worker return false;
546*795d594fSAndroid Build Coastguard Worker }
547*795d594fSAndroid Build Coastguard Worker
548*795d594fSAndroid Build Coastguard Worker // Emit a field variable.
emitFieldVariable(Type tp)549*795d594fSAndroid Build Coastguard Worker void emitFieldVariable(Type tp) {
550*795d594fSAndroid Build Coastguard Worker switch (tp) {
551*795d594fSAndroid Build Coastguard Worker case kBoolean:fputs("mZ", out_); break;
552*795d594fSAndroid Build Coastguard Worker case kInt: fputs("mI", out_); break;
553*795d594fSAndroid Build Coastguard Worker case kLong: fputs("mJ", out_); break;
554*795d594fSAndroid Build Coastguard Worker case kFloat: fputs("mF", out_); break;
555*795d594fSAndroid Build Coastguard Worker case kDouble: fputs("mD", out_); break;
556*795d594fSAndroid Build Coastguard Worker }
557*795d594fSAndroid Build Coastguard Worker }
558*795d594fSAndroid Build Coastguard Worker
559*795d594fSAndroid Build Coastguard Worker // Emit a variable.
emitVariable(Type tp)560*795d594fSAndroid Build Coastguard Worker void emitVariable(Type tp) {
561*795d594fSAndroid Build Coastguard Worker switch (random1(4)) {
562*795d594fSAndroid Build Coastguard Worker case 1:
563*795d594fSAndroid Build Coastguard Worker if (emitArrayVariable(tp))
564*795d594fSAndroid Build Coastguard Worker return;
565*795d594fSAndroid Build Coastguard Worker [[fallthrough]];
566*795d594fSAndroid Build Coastguard Worker case 2:
567*795d594fSAndroid Build Coastguard Worker if (emitLocalVariable(tp))
568*795d594fSAndroid Build Coastguard Worker return;
569*795d594fSAndroid Build Coastguard Worker [[fallthrough]];
570*795d594fSAndroid Build Coastguard Worker default:
571*795d594fSAndroid Build Coastguard Worker emitFieldVariable(tp);
572*795d594fSAndroid Build Coastguard Worker break;
573*795d594fSAndroid Build Coastguard Worker }
574*795d594fSAndroid Build Coastguard Worker }
575*795d594fSAndroid Build Coastguard Worker
576*795d594fSAndroid Build Coastguard Worker // Emit an expression.
emitExpression(Type tp)577*795d594fSAndroid Build Coastguard Worker void emitExpression(Type tp) {
578*795d594fSAndroid Build Coastguard Worker // Continuing expression becomes less likely as the depth grows.
579*795d594fSAndroid Build Coastguard Worker if (random1(expr_depth_ + 1) > fuzz_expr_depth_) {
580*795d594fSAndroid Build Coastguard Worker if (random1(2) == 1) {
581*795d594fSAndroid Build Coastguard Worker emitLiteral(tp);
582*795d594fSAndroid Build Coastguard Worker } else {
583*795d594fSAndroid Build Coastguard Worker emitVariable(tp);
584*795d594fSAndroid Build Coastguard Worker }
585*795d594fSAndroid Build Coastguard Worker return;
586*795d594fSAndroid Build Coastguard Worker }
587*795d594fSAndroid Build Coastguard Worker
588*795d594fSAndroid Build Coastguard Worker expr_depth_++;
589*795d594fSAndroid Build Coastguard Worker
590*795d594fSAndroid Build Coastguard Worker fputc('(', out_);
591*795d594fSAndroid Build Coastguard Worker switch (random1(12)) { // favor binary operations
592*795d594fSAndroid Build Coastguard Worker case 1:
593*795d594fSAndroid Build Coastguard Worker // Unary operator: ~ x
594*795d594fSAndroid Build Coastguard Worker emitUnaryOp(tp);
595*795d594fSAndroid Build Coastguard Worker fputc(' ', out_);
596*795d594fSAndroid Build Coastguard Worker emitExpression(tp);
597*795d594fSAndroid Build Coastguard Worker break;
598*795d594fSAndroid Build Coastguard Worker case 2:
599*795d594fSAndroid Build Coastguard Worker // Pre-increment: ++x
600*795d594fSAndroid Build Coastguard Worker emitIncDecOp(tp);
601*795d594fSAndroid Build Coastguard Worker emitVariable(tp);
602*795d594fSAndroid Build Coastguard Worker break;
603*795d594fSAndroid Build Coastguard Worker case 3:
604*795d594fSAndroid Build Coastguard Worker // Post-increment: x++
605*795d594fSAndroid Build Coastguard Worker emitVariable(tp);
606*795d594fSAndroid Build Coastguard Worker emitIncDecOp(tp);
607*795d594fSAndroid Build Coastguard Worker break;
608*795d594fSAndroid Build Coastguard Worker case 4:
609*795d594fSAndroid Build Coastguard Worker // Ternary operator: b ? x : y
610*795d594fSAndroid Build Coastguard Worker emitExpression(kBoolean);
611*795d594fSAndroid Build Coastguard Worker fputs(" ? ", out_);
612*795d594fSAndroid Build Coastguard Worker emitExpression(tp);
613*795d594fSAndroid Build Coastguard Worker fputs(" : ", out_);
614*795d594fSAndroid Build Coastguard Worker emitExpression(tp);
615*795d594fSAndroid Build Coastguard Worker break;
616*795d594fSAndroid Build Coastguard Worker case 5:
617*795d594fSAndroid Build Coastguard Worker // Type conversion: (float) x
618*795d594fSAndroid Build Coastguard Worker emitTypeConversion(tp);
619*795d594fSAndroid Build Coastguard Worker break;
620*795d594fSAndroid Build Coastguard Worker case 6:
621*795d594fSAndroid Build Coastguard Worker // Intrinsic: foo(x)
622*795d594fSAndroid Build Coastguard Worker emitIntrinsic(tp);
623*795d594fSAndroid Build Coastguard Worker break;
624*795d594fSAndroid Build Coastguard Worker case 7:
625*795d594fSAndroid Build Coastguard Worker // Method call: mA.a()
626*795d594fSAndroid Build Coastguard Worker emitMethodCall(tp);
627*795d594fSAndroid Build Coastguard Worker break;
628*795d594fSAndroid Build Coastguard Worker case 8:
629*795d594fSAndroid Build Coastguard Worker // Emit unboxing boxed value: (int) Integer(x)
630*795d594fSAndroid Build Coastguard Worker emitUnbox(tp);
631*795d594fSAndroid Build Coastguard Worker break;
632*795d594fSAndroid Build Coastguard Worker case 9:
633*795d594fSAndroid Build Coastguard Worker // Miscellaneous constructs: a.length
634*795d594fSAndroid Build Coastguard Worker emitMisc(tp);
635*795d594fSAndroid Build Coastguard Worker break;
636*795d594fSAndroid Build Coastguard Worker default:
637*795d594fSAndroid Build Coastguard Worker // Binary operator: x + y
638*795d594fSAndroid Build Coastguard Worker emitExpression(tp);
639*795d594fSAndroid Build Coastguard Worker fputc(' ', out_);
640*795d594fSAndroid Build Coastguard Worker emitBinaryOp(tp);
641*795d594fSAndroid Build Coastguard Worker fputc(' ', out_);
642*795d594fSAndroid Build Coastguard Worker emitExpression(tp);
643*795d594fSAndroid Build Coastguard Worker break;
644*795d594fSAndroid Build Coastguard Worker }
645*795d594fSAndroid Build Coastguard Worker fputc(')', out_);
646*795d594fSAndroid Build Coastguard Worker
647*795d594fSAndroid Build Coastguard Worker --expr_depth_;
648*795d594fSAndroid Build Coastguard Worker }
649*795d594fSAndroid Build Coastguard Worker
650*795d594fSAndroid Build Coastguard Worker //
651*795d594fSAndroid Build Coastguard Worker // Statements.
652*795d594fSAndroid Build Coastguard Worker //
653*795d594fSAndroid Build Coastguard Worker
654*795d594fSAndroid Build Coastguard Worker // Emit current indentation.
emitIndentation() const655*795d594fSAndroid Build Coastguard Worker void emitIndentation() const {
656*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < indentation_; i++) {
657*795d594fSAndroid Build Coastguard Worker fputc(' ', out_);
658*795d594fSAndroid Build Coastguard Worker }
659*795d594fSAndroid Build Coastguard Worker }
660*795d594fSAndroid Build Coastguard Worker
661*795d594fSAndroid Build Coastguard Worker // Emit a return statement.
emitReturn(bool mustEmit)662*795d594fSAndroid Build Coastguard Worker bool emitReturn(bool mustEmit) {
663*795d594fSAndroid Build Coastguard Worker // Only emit when we must, or with low probability inside ifs/loops,
664*795d594fSAndroid Build Coastguard Worker // but outside do-while to avoid confusing the may follow status.
665*795d594fSAndroid Build Coastguard Worker if (mustEmit || ((if_nest_ + loop_nest_) > 0 && do_nest_ == 0 && random1(10) == 1)) {
666*795d594fSAndroid Build Coastguard Worker fputs("return ", out_);
667*795d594fSAndroid Build Coastguard Worker emitExpression(return_type_);
668*795d594fSAndroid Build Coastguard Worker fputs(";\n", out_);
669*795d594fSAndroid Build Coastguard Worker return false;
670*795d594fSAndroid Build Coastguard Worker }
671*795d594fSAndroid Build Coastguard Worker // Fall back to assignment.
672*795d594fSAndroid Build Coastguard Worker return emitAssignment();
673*795d594fSAndroid Build Coastguard Worker }
674*795d594fSAndroid Build Coastguard Worker
675*795d594fSAndroid Build Coastguard Worker // Emit a continue statement.
emitContinue()676*795d594fSAndroid Build Coastguard Worker bool emitContinue() {
677*795d594fSAndroid Build Coastguard Worker // Only emit with low probability inside loops.
678*795d594fSAndroid Build Coastguard Worker if (loop_nest_ > 0 && random1(10) == 1) {
679*795d594fSAndroid Build Coastguard Worker fputs("continue;\n", out_);
680*795d594fSAndroid Build Coastguard Worker return false;
681*795d594fSAndroid Build Coastguard Worker }
682*795d594fSAndroid Build Coastguard Worker // Fall back to assignment.
683*795d594fSAndroid Build Coastguard Worker return emitAssignment();
684*795d594fSAndroid Build Coastguard Worker }
685*795d594fSAndroid Build Coastguard Worker
686*795d594fSAndroid Build Coastguard Worker // Emit a break statement.
emitBreak()687*795d594fSAndroid Build Coastguard Worker bool emitBreak() {
688*795d594fSAndroid Build Coastguard Worker // Only emit with low probability inside loops, but outside switches
689*795d594fSAndroid Build Coastguard Worker // to avoid confusing the may follow status.
690*795d594fSAndroid Build Coastguard Worker if (loop_nest_ > 0 && switch_nest_ == 0 && random1(10) == 1) {
691*795d594fSAndroid Build Coastguard Worker fputs("break;\n", out_);
692*795d594fSAndroid Build Coastguard Worker return false;
693*795d594fSAndroid Build Coastguard Worker }
694*795d594fSAndroid Build Coastguard Worker // Fall back to assignment.
695*795d594fSAndroid Build Coastguard Worker return emitAssignment();
696*795d594fSAndroid Build Coastguard Worker }
697*795d594fSAndroid Build Coastguard Worker
698*795d594fSAndroid Build Coastguard Worker // Emit a new scope with a local variable declaration statement.
emitScope()699*795d594fSAndroid Build Coastguard Worker bool emitScope() {
700*795d594fSAndroid Build Coastguard Worker Type tp = randomType();
701*795d594fSAndroid Build Coastguard Worker fputs("{\n", out_);
702*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
703*795d594fSAndroid Build Coastguard Worker emitIndentation();
704*795d594fSAndroid Build Coastguard Worker emitType(tp);
705*795d594fSAndroid Build Coastguard Worker switch (tp) {
706*795d594fSAndroid Build Coastguard Worker case kBoolean: fprintf(out_, " lZ%u = ", boolean_local_); break;
707*795d594fSAndroid Build Coastguard Worker case kInt: fprintf(out_, " lI%u = ", int_local_); break;
708*795d594fSAndroid Build Coastguard Worker case kLong: fprintf(out_, " lJ%u = ", long_local_); break;
709*795d594fSAndroid Build Coastguard Worker case kFloat: fprintf(out_, " lF%u = ", float_local_); break;
710*795d594fSAndroid Build Coastguard Worker case kDouble: fprintf(out_, " lD%u = ", double_local_); break;
711*795d594fSAndroid Build Coastguard Worker }
712*795d594fSAndroid Build Coastguard Worker emitExpression(tp);
713*795d594fSAndroid Build Coastguard Worker fputs(";\n", out_);
714*795d594fSAndroid Build Coastguard Worker
715*795d594fSAndroid Build Coastguard Worker adjustLocal(tp, 1); // local now visible
716*795d594fSAndroid Build Coastguard Worker
717*795d594fSAndroid Build Coastguard Worker bool mayFollow = emitStatementList();
718*795d594fSAndroid Build Coastguard Worker
719*795d594fSAndroid Build Coastguard Worker adjustLocal(tp, -1); // local no longer visible
720*795d594fSAndroid Build Coastguard Worker
721*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
722*795d594fSAndroid Build Coastguard Worker emitIndentation();
723*795d594fSAndroid Build Coastguard Worker fputs("}\n", out_);
724*795d594fSAndroid Build Coastguard Worker return mayFollow;
725*795d594fSAndroid Build Coastguard Worker }
726*795d594fSAndroid Build Coastguard Worker
727*795d594fSAndroid Build Coastguard Worker // Emit one dimension of an array initializer, where parameter dim >= 1
728*795d594fSAndroid Build Coastguard Worker // denotes the number of remaining dimensions that should be emitted.
emitArrayInitDim(int dim)729*795d594fSAndroid Build Coastguard Worker void emitArrayInitDim(int dim) {
730*795d594fSAndroid Build Coastguard Worker if (dim == 1) {
731*795d594fSAndroid Build Coastguard Worker // Last dimension: set of values.
732*795d594fSAndroid Build Coastguard Worker fputs("{ ", out_);
733*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < array_size_; i++) {
734*795d594fSAndroid Build Coastguard Worker emitExpression(array_type_);
735*795d594fSAndroid Build Coastguard Worker fputs(", ", out_);
736*795d594fSAndroid Build Coastguard Worker }
737*795d594fSAndroid Build Coastguard Worker fputs("}", out_);
738*795d594fSAndroid Build Coastguard Worker
739*795d594fSAndroid Build Coastguard Worker } else {
740*795d594fSAndroid Build Coastguard Worker // Outer dimensions: set of sets.
741*795d594fSAndroid Build Coastguard Worker fputs("{\n", out_);
742*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
743*795d594fSAndroid Build Coastguard Worker emitIndentation();
744*795d594fSAndroid Build Coastguard Worker
745*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < array_size_; i++) {
746*795d594fSAndroid Build Coastguard Worker emitArrayInitDim(dim - 1);
747*795d594fSAndroid Build Coastguard Worker if (i != array_size_ - 1) {
748*795d594fSAndroid Build Coastguard Worker fputs(",\n", out_);
749*795d594fSAndroid Build Coastguard Worker emitIndentation();
750*795d594fSAndroid Build Coastguard Worker }
751*795d594fSAndroid Build Coastguard Worker }
752*795d594fSAndroid Build Coastguard Worker
753*795d594fSAndroid Build Coastguard Worker fputs(",\n", out_);
754*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
755*795d594fSAndroid Build Coastguard Worker emitIndentation();
756*795d594fSAndroid Build Coastguard Worker fputs("}", out_);
757*795d594fSAndroid Build Coastguard Worker }
758*795d594fSAndroid Build Coastguard Worker }
759*795d594fSAndroid Build Coastguard Worker
760*795d594fSAndroid Build Coastguard Worker // Emit an array initializer of the following form.
761*795d594fSAndroid Build Coastguard Worker // {
762*795d594fSAndroid Build Coastguard Worker // type[]..[] tmp = { .. };
763*795d594fSAndroid Build Coastguard Worker // mArray = tmp;
764*795d594fSAndroid Build Coastguard Worker // }
emitArrayInit()765*795d594fSAndroid Build Coastguard Worker bool emitArrayInit() {
766*795d594fSAndroid Build Coastguard Worker // Avoid elaborate array initializers.
767*795d594fSAndroid Build Coastguard Worker uint64_t p = pow(array_size_, array_dim_);
768*795d594fSAndroid Build Coastguard Worker if (p > 20) {
769*795d594fSAndroid Build Coastguard Worker return emitAssignment(); // fall back
770*795d594fSAndroid Build Coastguard Worker }
771*795d594fSAndroid Build Coastguard Worker
772*795d594fSAndroid Build Coastguard Worker fputs("{\n", out_);
773*795d594fSAndroid Build Coastguard Worker
774*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
775*795d594fSAndroid Build Coastguard Worker emitIndentation();
776*795d594fSAndroid Build Coastguard Worker emitType(array_type_);
777*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < array_dim_; i++) {
778*795d594fSAndroid Build Coastguard Worker fputs("[]", out_);
779*795d594fSAndroid Build Coastguard Worker }
780*795d594fSAndroid Build Coastguard Worker fputs(" tmp = ", out_);
781*795d594fSAndroid Build Coastguard Worker emitArrayInitDim(array_dim_);
782*795d594fSAndroid Build Coastguard Worker fputs(";\n", out_);
783*795d594fSAndroid Build Coastguard Worker
784*795d594fSAndroid Build Coastguard Worker emitIndentation();
785*795d594fSAndroid Build Coastguard Worker fputs("mArray = tmp;\n", out_);
786*795d594fSAndroid Build Coastguard Worker
787*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
788*795d594fSAndroid Build Coastguard Worker emitIndentation();
789*795d594fSAndroid Build Coastguard Worker fputs("}\n", out_);
790*795d594fSAndroid Build Coastguard Worker return true;
791*795d594fSAndroid Build Coastguard Worker }
792*795d594fSAndroid Build Coastguard Worker
793*795d594fSAndroid Build Coastguard Worker // Emit a for loop.
emitForLoop()794*795d594fSAndroid Build Coastguard Worker bool emitForLoop() {
795*795d594fSAndroid Build Coastguard Worker // Continuing loop nest becomes less likely as the depth grows.
796*795d594fSAndroid Build Coastguard Worker if (random1(loop_nest_ + 1) > fuzz_loop_nest_) {
797*795d594fSAndroid Build Coastguard Worker return emitAssignment(); // fall back
798*795d594fSAndroid Build Coastguard Worker }
799*795d594fSAndroid Build Coastguard Worker
800*795d594fSAndroid Build Coastguard Worker bool goesUp = random1(2) == 1;
801*795d594fSAndroid Build Coastguard Worker fprintf(out_, "for (int i%u = ", loop_nest_);
802*795d594fSAndroid Build Coastguard Worker if (goesUp) {
803*795d594fSAndroid Build Coastguard Worker fprintf(out_, "0; i%u < ", loop_nest_);
804*795d594fSAndroid Build Coastguard Worker emitUpperBound();
805*795d594fSAndroid Build Coastguard Worker fprintf(out_, "; i%u++) {\n", loop_nest_);
806*795d594fSAndroid Build Coastguard Worker } else {
807*795d594fSAndroid Build Coastguard Worker emitUpperBound();
808*795d594fSAndroid Build Coastguard Worker fprintf(out_, " - 1; i%d >= 0", loop_nest_);
809*795d594fSAndroid Build Coastguard Worker fprintf(out_, "; i%d--) {\n", loop_nest_);
810*795d594fSAndroid Build Coastguard Worker }
811*795d594fSAndroid Build Coastguard Worker
812*795d594fSAndroid Build Coastguard Worker ++loop_nest_; // now in loop
813*795d594fSAndroid Build Coastguard Worker
814*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
815*795d594fSAndroid Build Coastguard Worker emitStatementList();
816*795d594fSAndroid Build Coastguard Worker
817*795d594fSAndroid Build Coastguard Worker --loop_nest_; // no longer in loop
818*795d594fSAndroid Build Coastguard Worker
819*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
820*795d594fSAndroid Build Coastguard Worker emitIndentation();
821*795d594fSAndroid Build Coastguard Worker fprintf(out_, "}\n");
822*795d594fSAndroid Build Coastguard Worker return true; // loop-body does not block flow
823*795d594fSAndroid Build Coastguard Worker }
824*795d594fSAndroid Build Coastguard Worker
825*795d594fSAndroid Build Coastguard Worker // Emit while or do-while loop.
emitDoLoop()826*795d594fSAndroid Build Coastguard Worker bool emitDoLoop() {
827*795d594fSAndroid Build Coastguard Worker // Continuing loop nest becomes less likely as the depth grows.
828*795d594fSAndroid Build Coastguard Worker if (random1(loop_nest_ + 1) > fuzz_loop_nest_) {
829*795d594fSAndroid Build Coastguard Worker return emitAssignment(); // fall back
830*795d594fSAndroid Build Coastguard Worker }
831*795d594fSAndroid Build Coastguard Worker
832*795d594fSAndroid Build Coastguard Worker bool isWhile = random1(2) == 1;
833*795d594fSAndroid Build Coastguard Worker fputs("{\n", out_);
834*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
835*795d594fSAndroid Build Coastguard Worker emitIndentation();
836*795d594fSAndroid Build Coastguard Worker fprintf(out_, "int i%u = %d;\n", loop_nest_, isWhile ? -1 : 0);
837*795d594fSAndroid Build Coastguard Worker emitIndentation();
838*795d594fSAndroid Build Coastguard Worker if (isWhile) {
839*795d594fSAndroid Build Coastguard Worker fprintf(out_, "while (++i%u < ", loop_nest_);
840*795d594fSAndroid Build Coastguard Worker emitUpperBound();
841*795d594fSAndroid Build Coastguard Worker fputs(") {\n", out_);
842*795d594fSAndroid Build Coastguard Worker } else {
843*795d594fSAndroid Build Coastguard Worker fputs("do {\n", out_);
844*795d594fSAndroid Build Coastguard Worker do_nest_++;
845*795d594fSAndroid Build Coastguard Worker }
846*795d594fSAndroid Build Coastguard Worker
847*795d594fSAndroid Build Coastguard Worker ++loop_nest_; // now in loop
848*795d594fSAndroid Build Coastguard Worker
849*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
850*795d594fSAndroid Build Coastguard Worker emitStatementList();
851*795d594fSAndroid Build Coastguard Worker
852*795d594fSAndroid Build Coastguard Worker --loop_nest_; // no longer in loop
853*795d594fSAndroid Build Coastguard Worker
854*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
855*795d594fSAndroid Build Coastguard Worker emitIndentation();
856*795d594fSAndroid Build Coastguard Worker if (isWhile) {
857*795d594fSAndroid Build Coastguard Worker fputs("}\n", out_);
858*795d594fSAndroid Build Coastguard Worker } else {
859*795d594fSAndroid Build Coastguard Worker fprintf(out_, "} while (++i%u < ", loop_nest_);
860*795d594fSAndroid Build Coastguard Worker emitUpperBound();
861*795d594fSAndroid Build Coastguard Worker fputs(");\n", out_);
862*795d594fSAndroid Build Coastguard Worker --do_nest_;
863*795d594fSAndroid Build Coastguard Worker }
864*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
865*795d594fSAndroid Build Coastguard Worker emitIndentation();
866*795d594fSAndroid Build Coastguard Worker fputs("}\n", out_);
867*795d594fSAndroid Build Coastguard Worker return true; // loop-body does not block flow
868*795d594fSAndroid Build Coastguard Worker }
869*795d594fSAndroid Build Coastguard Worker
870*795d594fSAndroid Build Coastguard Worker // Emit an if statement.
emitIfStmt()871*795d594fSAndroid Build Coastguard Worker bool emitIfStmt() {
872*795d594fSAndroid Build Coastguard Worker // Continuing if nest becomes less likely as the depth grows.
873*795d594fSAndroid Build Coastguard Worker if (random1(if_nest_ + 1) > fuzz_if_nest_) {
874*795d594fSAndroid Build Coastguard Worker return emitAssignment(); // fall back
875*795d594fSAndroid Build Coastguard Worker }
876*795d594fSAndroid Build Coastguard Worker
877*795d594fSAndroid Build Coastguard Worker fputs("if (", out_);
878*795d594fSAndroid Build Coastguard Worker emitExpression(kBoolean);
879*795d594fSAndroid Build Coastguard Worker fputs(") {\n", out_);
880*795d594fSAndroid Build Coastguard Worker
881*795d594fSAndroid Build Coastguard Worker ++if_nest_; // now in if
882*795d594fSAndroid Build Coastguard Worker
883*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
884*795d594fSAndroid Build Coastguard Worker bool mayFollowTrue = emitStatementList();
885*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
886*795d594fSAndroid Build Coastguard Worker emitIndentation();
887*795d594fSAndroid Build Coastguard Worker fprintf(out_, "} else {\n");
888*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
889*795d594fSAndroid Build Coastguard Worker bool mayFollowFalse = emitStatementList();
890*795d594fSAndroid Build Coastguard Worker
891*795d594fSAndroid Build Coastguard Worker --if_nest_; // no longer in if
892*795d594fSAndroid Build Coastguard Worker
893*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
894*795d594fSAndroid Build Coastguard Worker emitIndentation();
895*795d594fSAndroid Build Coastguard Worker fprintf(out_, "}\n");
896*795d594fSAndroid Build Coastguard Worker return mayFollowTrue || mayFollowFalse;
897*795d594fSAndroid Build Coastguard Worker }
898*795d594fSAndroid Build Coastguard Worker
emitTry()899*795d594fSAndroid Build Coastguard Worker bool emitTry() {
900*795d594fSAndroid Build Coastguard Worker fputs("try {\n", out_);
901*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
902*795d594fSAndroid Build Coastguard Worker bool mayFollow = emitStatementList();
903*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
904*795d594fSAndroid Build Coastguard Worker emitIndentation();
905*795d594fSAndroid Build Coastguard Worker fputc('}', out_);
906*795d594fSAndroid Build Coastguard Worker return mayFollow;
907*795d594fSAndroid Build Coastguard Worker }
908*795d594fSAndroid Build Coastguard Worker
emitCatch()909*795d594fSAndroid Build Coastguard Worker bool emitCatch() {
910*795d594fSAndroid Build Coastguard Worker uint32_t count = random1(countof(kExceptionTypes));
911*795d594fSAndroid Build Coastguard Worker bool mayFollow = false;
912*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < count; ++i) {
913*795d594fSAndroid Build Coastguard Worker fprintf(out_, " catch (%s ex%u_%u) {\n", kExceptionTypes[i], try_nest_, i);
914*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
915*795d594fSAndroid Build Coastguard Worker mayFollow |= emitStatementList();
916*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
917*795d594fSAndroid Build Coastguard Worker emitIndentation();
918*795d594fSAndroid Build Coastguard Worker fputc('}', out_);
919*795d594fSAndroid Build Coastguard Worker }
920*795d594fSAndroid Build Coastguard Worker return mayFollow;
921*795d594fSAndroid Build Coastguard Worker }
922*795d594fSAndroid Build Coastguard Worker
emitFinally()923*795d594fSAndroid Build Coastguard Worker bool emitFinally() {
924*795d594fSAndroid Build Coastguard Worker fputs(" finally {\n", out_);
925*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
926*795d594fSAndroid Build Coastguard Worker bool mayFollow = emitStatementList();
927*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
928*795d594fSAndroid Build Coastguard Worker emitIndentation();
929*795d594fSAndroid Build Coastguard Worker fputc('}', out_);
930*795d594fSAndroid Build Coastguard Worker return mayFollow;
931*795d594fSAndroid Build Coastguard Worker }
932*795d594fSAndroid Build Coastguard Worker
933*795d594fSAndroid Build Coastguard Worker // Emit a try-catch-finally block.
emitTryCatchFinally()934*795d594fSAndroid Build Coastguard Worker bool emitTryCatchFinally() {
935*795d594fSAndroid Build Coastguard Worker // Apply a hard limit on the number of catch blocks. This is for
936*795d594fSAndroid Build Coastguard Worker // javac which fails if blocks within try-catch-finally are too
937*795d594fSAndroid Build Coastguard Worker // large (much less than you'd expect).
938*795d594fSAndroid Build Coastguard Worker if (try_nest_ > fuzz_try_nest_) {
939*795d594fSAndroid Build Coastguard Worker return emitAssignment(); // fall back
940*795d594fSAndroid Build Coastguard Worker }
941*795d594fSAndroid Build Coastguard Worker
942*795d594fSAndroid Build Coastguard Worker ++try_nest_; // Entering try-catch-finally
943*795d594fSAndroid Build Coastguard Worker
944*795d594fSAndroid Build Coastguard Worker bool mayFollow = emitTry();
945*795d594fSAndroid Build Coastguard Worker switch (random0(3)) {
946*795d594fSAndroid Build Coastguard Worker case 0: // try..catch
947*795d594fSAndroid Build Coastguard Worker mayFollow |= emitCatch();
948*795d594fSAndroid Build Coastguard Worker break;
949*795d594fSAndroid Build Coastguard Worker case 1: // try..finally
950*795d594fSAndroid Build Coastguard Worker mayFollow &= emitFinally();
951*795d594fSAndroid Build Coastguard Worker break;
952*795d594fSAndroid Build Coastguard Worker case 2: // try..catch..finally
953*795d594fSAndroid Build Coastguard Worker // When determining whether code may follow, we observe that a
954*795d594fSAndroid Build Coastguard Worker // finally block always follows after try and catch
955*795d594fSAndroid Build Coastguard Worker // block. Code may only follow if the finally block permits
956*795d594fSAndroid Build Coastguard Worker // and either the try or catch block allows code to follow.
957*795d594fSAndroid Build Coastguard Worker mayFollow = (mayFollow | emitCatch());
958*795d594fSAndroid Build Coastguard Worker mayFollow &= emitFinally();
959*795d594fSAndroid Build Coastguard Worker break;
960*795d594fSAndroid Build Coastguard Worker }
961*795d594fSAndroid Build Coastguard Worker fputc('\n', out_);
962*795d594fSAndroid Build Coastguard Worker
963*795d594fSAndroid Build Coastguard Worker --try_nest_; // Leaving try-catch-finally
964*795d594fSAndroid Build Coastguard Worker return mayFollow;
965*795d594fSAndroid Build Coastguard Worker }
966*795d594fSAndroid Build Coastguard Worker
967*795d594fSAndroid Build Coastguard Worker // Emit a switch statement.
emitSwitch()968*795d594fSAndroid Build Coastguard Worker bool emitSwitch() {
969*795d594fSAndroid Build Coastguard Worker // Continuing if nest becomes less likely as the depth grows.
970*795d594fSAndroid Build Coastguard Worker if (random1(if_nest_ + 1) > fuzz_if_nest_) {
971*795d594fSAndroid Build Coastguard Worker return emitAssignment(); // fall back
972*795d594fSAndroid Build Coastguard Worker }
973*795d594fSAndroid Build Coastguard Worker
974*795d594fSAndroid Build Coastguard Worker bool mayFollow = false;
975*795d594fSAndroid Build Coastguard Worker fputs("switch (", out_);
976*795d594fSAndroid Build Coastguard Worker emitArrayIndex(); // restrict its range
977*795d594fSAndroid Build Coastguard Worker fputs(") {\n", out_);
978*795d594fSAndroid Build Coastguard Worker
979*795d594fSAndroid Build Coastguard Worker ++if_nest_;
980*795d594fSAndroid Build Coastguard Worker ++switch_nest_; // now in switch
981*795d594fSAndroid Build Coastguard Worker
982*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
983*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < 2; i++) {
984*795d594fSAndroid Build Coastguard Worker emitIndentation();
985*795d594fSAndroid Build Coastguard Worker if (i == 0) {
986*795d594fSAndroid Build Coastguard Worker fprintf(out_, "case %u: {\n", random0(array_size_));
987*795d594fSAndroid Build Coastguard Worker } else {
988*795d594fSAndroid Build Coastguard Worker fprintf(out_, "default: {\n");
989*795d594fSAndroid Build Coastguard Worker }
990*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
991*795d594fSAndroid Build Coastguard Worker if (emitStatementList()) {
992*795d594fSAndroid Build Coastguard Worker // Must end with break.
993*795d594fSAndroid Build Coastguard Worker emitIndentation();
994*795d594fSAndroid Build Coastguard Worker fputs("break;\n", out_);
995*795d594fSAndroid Build Coastguard Worker mayFollow = true;
996*795d594fSAndroid Build Coastguard Worker }
997*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
998*795d594fSAndroid Build Coastguard Worker emitIndentation();
999*795d594fSAndroid Build Coastguard Worker fputs("}\n", out_);
1000*795d594fSAndroid Build Coastguard Worker }
1001*795d594fSAndroid Build Coastguard Worker
1002*795d594fSAndroid Build Coastguard Worker --if_nest_;
1003*795d594fSAndroid Build Coastguard Worker --switch_nest_; // no longer in switch
1004*795d594fSAndroid Build Coastguard Worker
1005*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
1006*795d594fSAndroid Build Coastguard Worker emitIndentation();
1007*795d594fSAndroid Build Coastguard Worker fprintf(out_, "}\n");
1008*795d594fSAndroid Build Coastguard Worker return mayFollow;
1009*795d594fSAndroid Build Coastguard Worker }
1010*795d594fSAndroid Build Coastguard Worker
emitNopCall()1011*795d594fSAndroid Build Coastguard Worker bool emitNopCall() {
1012*795d594fSAndroid Build Coastguard Worker fputs("nop();\n", out_);
1013*795d594fSAndroid Build Coastguard Worker return true;
1014*795d594fSAndroid Build Coastguard Worker }
1015*795d594fSAndroid Build Coastguard Worker
1016*795d594fSAndroid Build Coastguard Worker // Emit an assignment statement.
emitAssignment()1017*795d594fSAndroid Build Coastguard Worker bool emitAssignment() {
1018*795d594fSAndroid Build Coastguard Worker Type tp = randomType();
1019*795d594fSAndroid Build Coastguard Worker emitVariable(tp);
1020*795d594fSAndroid Build Coastguard Worker fputc(' ', out_);
1021*795d594fSAndroid Build Coastguard Worker emitAssignmentOp(tp);
1022*795d594fSAndroid Build Coastguard Worker fputc(' ', out_);
1023*795d594fSAndroid Build Coastguard Worker emitExpression(tp);
1024*795d594fSAndroid Build Coastguard Worker fputs(";\n", out_);
1025*795d594fSAndroid Build Coastguard Worker return true;
1026*795d594fSAndroid Build Coastguard Worker }
1027*795d594fSAndroid Build Coastguard Worker
1028*795d594fSAndroid Build Coastguard Worker // Emit a single statement. Returns true if statements may follow.
emitStatement()1029*795d594fSAndroid Build Coastguard Worker bool emitStatement() {
1030*795d594fSAndroid Build Coastguard Worker switch (random1(16)) { // favor assignments
1031*795d594fSAndroid Build Coastguard Worker case 1: return emitReturn(false); break;
1032*795d594fSAndroid Build Coastguard Worker case 2: return emitContinue(); break;
1033*795d594fSAndroid Build Coastguard Worker case 3: return emitBreak(); break;
1034*795d594fSAndroid Build Coastguard Worker case 4: return emitScope(); break;
1035*795d594fSAndroid Build Coastguard Worker case 5: return emitArrayInit(); break;
1036*795d594fSAndroid Build Coastguard Worker case 6: return emitForLoop(); break;
1037*795d594fSAndroid Build Coastguard Worker case 7: return emitDoLoop(); break;
1038*795d594fSAndroid Build Coastguard Worker case 8: return emitIfStmt(); break;
1039*795d594fSAndroid Build Coastguard Worker case 9: return emitSwitch(); break;
1040*795d594fSAndroid Build Coastguard Worker case 10: return emitTryCatchFinally(); break;
1041*795d594fSAndroid Build Coastguard Worker case 11: return emitNopCall(); break;
1042*795d594fSAndroid Build Coastguard Worker default: return emitAssignment(); break;
1043*795d594fSAndroid Build Coastguard Worker }
1044*795d594fSAndroid Build Coastguard Worker }
1045*795d594fSAndroid Build Coastguard Worker
1046*795d594fSAndroid Build Coastguard Worker // Emit a statement list. Returns true if statements may follow.
emitStatementList()1047*795d594fSAndroid Build Coastguard Worker bool emitStatementList() {
1048*795d594fSAndroid Build Coastguard Worker while (stmt_length_ < 1000) { // avoid run-away
1049*795d594fSAndroid Build Coastguard Worker stmt_length_++;
1050*795d594fSAndroid Build Coastguard Worker emitIndentation();
1051*795d594fSAndroid Build Coastguard Worker if (!emitStatement()) {
1052*795d594fSAndroid Build Coastguard Worker return false; // rest would be dead code
1053*795d594fSAndroid Build Coastguard Worker }
1054*795d594fSAndroid Build Coastguard Worker // Continuing this list becomes less likely as the total statement list grows.
1055*795d594fSAndroid Build Coastguard Worker if (random1(stmt_length_) > fuzz_stmt_length_) {
1056*795d594fSAndroid Build Coastguard Worker break;
1057*795d594fSAndroid Build Coastguard Worker }
1058*795d594fSAndroid Build Coastguard Worker }
1059*795d594fSAndroid Build Coastguard Worker return true;
1060*795d594fSAndroid Build Coastguard Worker }
1061*795d594fSAndroid Build Coastguard Worker
1062*795d594fSAndroid Build Coastguard Worker // Emit interface and class declarations.
emitClassDecls()1063*795d594fSAndroid Build Coastguard Worker void emitClassDecls() {
1064*795d594fSAndroid Build Coastguard Worker in_inner_ = true;
1065*795d594fSAndroid Build Coastguard Worker fputs(" private interface X {\n", out_);
1066*795d594fSAndroid Build Coastguard Worker fputs(" int x();\n", out_);
1067*795d594fSAndroid Build Coastguard Worker fputs(" }\n\n", out_);
1068*795d594fSAndroid Build Coastguard Worker fputs(" private class A {\n", out_);
1069*795d594fSAndroid Build Coastguard Worker fputs(" public int a() {\n", out_);
1070*795d594fSAndroid Build Coastguard Worker fputs(" return ", out_);
1071*795d594fSAndroid Build Coastguard Worker emitExpression(kInt);
1072*795d594fSAndroid Build Coastguard Worker fputs(";\n }\n", out_);
1073*795d594fSAndroid Build Coastguard Worker fputs(" }\n\n", out_);
1074*795d594fSAndroid Build Coastguard Worker fputs(" private class B extends A implements X {\n", out_);
1075*795d594fSAndroid Build Coastguard Worker fputs(" public int a() {\n", out_);
1076*795d594fSAndroid Build Coastguard Worker fputs(" return super.a() + ", out_);
1077*795d594fSAndroid Build Coastguard Worker emitExpression(kInt);
1078*795d594fSAndroid Build Coastguard Worker fputs(";\n }\n", out_);
1079*795d594fSAndroid Build Coastguard Worker fputs(" public int x() {\n", out_);
1080*795d594fSAndroid Build Coastguard Worker fputs(" return ", out_);
1081*795d594fSAndroid Build Coastguard Worker emitExpression(kInt);
1082*795d594fSAndroid Build Coastguard Worker fputs(";\n }\n", out_);
1083*795d594fSAndroid Build Coastguard Worker fputs(" }\n\n", out_);
1084*795d594fSAndroid Build Coastguard Worker fputs(" private static class C implements X {\n", out_);
1085*795d594fSAndroid Build Coastguard Worker fputs(" public static int s() {\n", out_);
1086*795d594fSAndroid Build Coastguard Worker fputs(" return ", out_);
1087*795d594fSAndroid Build Coastguard Worker emitLiteral(kInt);
1088*795d594fSAndroid Build Coastguard Worker fputs(";\n }\n", out_);
1089*795d594fSAndroid Build Coastguard Worker fputs(" public int c() {\n", out_);
1090*795d594fSAndroid Build Coastguard Worker fputs(" return ", out_);
1091*795d594fSAndroid Build Coastguard Worker emitLiteral(kInt);
1092*795d594fSAndroid Build Coastguard Worker fputs(";\n }\n", out_);
1093*795d594fSAndroid Build Coastguard Worker fputs(" public int x() {\n", out_);
1094*795d594fSAndroid Build Coastguard Worker fputs(" return ", out_);
1095*795d594fSAndroid Build Coastguard Worker emitLiteral(kInt);
1096*795d594fSAndroid Build Coastguard Worker fputs(";\n }\n", out_);
1097*795d594fSAndroid Build Coastguard Worker fputs(" }\n\n", out_);
1098*795d594fSAndroid Build Coastguard Worker in_inner_ = false;
1099*795d594fSAndroid Build Coastguard Worker }
1100*795d594fSAndroid Build Coastguard Worker
1101*795d594fSAndroid Build Coastguard Worker // Emit field declarations.
emitFieldDecls()1102*795d594fSAndroid Build Coastguard Worker void emitFieldDecls() {
1103*795d594fSAndroid Build Coastguard Worker fputs(" private A mA = new B();\n", out_);
1104*795d594fSAndroid Build Coastguard Worker fputs(" private B mB = new B();\n", out_);
1105*795d594fSAndroid Build Coastguard Worker fputs(" private X mBX = new B();\n", out_);
1106*795d594fSAndroid Build Coastguard Worker fputs(" private C mC = new C();\n", out_);
1107*795d594fSAndroid Build Coastguard Worker fputs(" private X mCX = new C();\n\n", out_);
1108*795d594fSAndroid Build Coastguard Worker fputs(" private boolean mZ = false;\n", out_);
1109*795d594fSAndroid Build Coastguard Worker fputs(" private int mI = 0;\n", out_);
1110*795d594fSAndroid Build Coastguard Worker fputs(" private long mJ = 0;\n", out_);
1111*795d594fSAndroid Build Coastguard Worker fputs(" private float mF = 0;\n", out_);
1112*795d594fSAndroid Build Coastguard Worker fputs(" private double mD = 0;\n\n", out_);
1113*795d594fSAndroid Build Coastguard Worker }
1114*795d594fSAndroid Build Coastguard Worker
1115*795d594fSAndroid Build Coastguard Worker // Emit array declaration.
emitArrayDecl()1116*795d594fSAndroid Build Coastguard Worker void emitArrayDecl() {
1117*795d594fSAndroid Build Coastguard Worker fputs(" private ", out_);
1118*795d594fSAndroid Build Coastguard Worker emitType(array_type_);
1119*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < array_dim_; i++) {
1120*795d594fSAndroid Build Coastguard Worker fputs("[]", out_);
1121*795d594fSAndroid Build Coastguard Worker }
1122*795d594fSAndroid Build Coastguard Worker fputs(" mArray = new ", out_);
1123*795d594fSAndroid Build Coastguard Worker emitType(array_type_);
1124*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < array_dim_; i++) {
1125*795d594fSAndroid Build Coastguard Worker fprintf(out_, "[%d]", array_size_);
1126*795d594fSAndroid Build Coastguard Worker }
1127*795d594fSAndroid Build Coastguard Worker fputs(";\n\n", out_);
1128*795d594fSAndroid Build Coastguard Worker }
1129*795d594fSAndroid Build Coastguard Worker
1130*795d594fSAndroid Build Coastguard Worker // Emit test constructor.
emitTestConstructor()1131*795d594fSAndroid Build Coastguard Worker void emitTestConstructor() {
1132*795d594fSAndroid Build Coastguard Worker fputs(" private Test() {\n", out_);
1133*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
1134*795d594fSAndroid Build Coastguard Worker emitIndentation();
1135*795d594fSAndroid Build Coastguard Worker emitType(array_type_);
1136*795d594fSAndroid Build Coastguard Worker fputs(" a = ", out_);
1137*795d594fSAndroid Build Coastguard Worker emitLiteral(array_type_);
1138*795d594fSAndroid Build Coastguard Worker fputs(";\n", out_);
1139*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < array_dim_; i++) {
1140*795d594fSAndroid Build Coastguard Worker emitIndentation();
1141*795d594fSAndroid Build Coastguard Worker fprintf(out_, "for (int i%u = 0; i%u < %u; i%u++) {\n", i, i, array_size_, i);
1142*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
1143*795d594fSAndroid Build Coastguard Worker }
1144*795d594fSAndroid Build Coastguard Worker emitIndentation();
1145*795d594fSAndroid Build Coastguard Worker fputs("mArray", out_);
1146*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < array_dim_; i++) {
1147*795d594fSAndroid Build Coastguard Worker fprintf(out_, "[i%u]", i);
1148*795d594fSAndroid Build Coastguard Worker }
1149*795d594fSAndroid Build Coastguard Worker fputs(" = a;\n", out_);
1150*795d594fSAndroid Build Coastguard Worker emitIndentation();
1151*795d594fSAndroid Build Coastguard Worker if (array_type_ == kBoolean) {
1152*795d594fSAndroid Build Coastguard Worker fputs("a = !a;\n", out_);
1153*795d594fSAndroid Build Coastguard Worker } else {
1154*795d594fSAndroid Build Coastguard Worker fputs("a++;\n", out_);
1155*795d594fSAndroid Build Coastguard Worker }
1156*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < array_dim_; i++) {
1157*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
1158*795d594fSAndroid Build Coastguard Worker emitIndentation();
1159*795d594fSAndroid Build Coastguard Worker fputs("}\n", out_);
1160*795d594fSAndroid Build Coastguard Worker }
1161*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
1162*795d594fSAndroid Build Coastguard Worker fputs(" }\n\n", out_);
1163*795d594fSAndroid Build Coastguard Worker }
1164*795d594fSAndroid Build Coastguard Worker
1165*795d594fSAndroid Build Coastguard Worker // Emit test method.
emitTestMethod()1166*795d594fSAndroid Build Coastguard Worker void emitTestMethod() {
1167*795d594fSAndroid Build Coastguard Worker fputs(" private ", out_);
1168*795d594fSAndroid Build Coastguard Worker emitType(return_type_);
1169*795d594fSAndroid Build Coastguard Worker fputs(" testMethod() {\n", out_);
1170*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
1171*795d594fSAndroid Build Coastguard Worker if (emitStatementList()) {
1172*795d594fSAndroid Build Coastguard Worker // Must end with return.
1173*795d594fSAndroid Build Coastguard Worker emitIndentation();
1174*795d594fSAndroid Build Coastguard Worker emitReturn(true);
1175*795d594fSAndroid Build Coastguard Worker }
1176*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
1177*795d594fSAndroid Build Coastguard Worker fputs(" }\n\n", out_);
1178*795d594fSAndroid Build Coastguard Worker }
1179*795d594fSAndroid Build Coastguard Worker
1180*795d594fSAndroid Build Coastguard Worker // Emit main method driver.
emitMainMethod()1181*795d594fSAndroid Build Coastguard Worker void emitMainMethod() {
1182*795d594fSAndroid Build Coastguard Worker fputs(" public static void main(String[] args) {\n", out_);
1183*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
1184*795d594fSAndroid Build Coastguard Worker fputs(" Test t = new Test();\n ", out_);
1185*795d594fSAndroid Build Coastguard Worker emitType(return_type_);
1186*795d594fSAndroid Build Coastguard Worker fputs(" r = ", out_);
1187*795d594fSAndroid Build Coastguard Worker emitLiteral(return_type_);
1188*795d594fSAndroid Build Coastguard Worker fputs(";\n", out_);
1189*795d594fSAndroid Build Coastguard Worker fputs(" try {\n", out_);
1190*795d594fSAndroid Build Coastguard Worker fputs(" r = t.testMethod();\n", out_);
1191*795d594fSAndroid Build Coastguard Worker fputs(" } catch (Exception e) {\n", out_);
1192*795d594fSAndroid Build Coastguard Worker fputs(" // Arithmetic, null pointer, index out of bounds, etc.\n", out_);
1193*795d594fSAndroid Build Coastguard Worker fputs(" System.out.println(\"An exception was caught.\");\n", out_);
1194*795d594fSAndroid Build Coastguard Worker fputs(" }\n", out_);
1195*795d594fSAndroid Build Coastguard Worker fputs(" System.out.println(\"r = \" + r);\n", out_);
1196*795d594fSAndroid Build Coastguard Worker fputs(" System.out.println(\"mZ = \" + t.mZ);\n", out_);
1197*795d594fSAndroid Build Coastguard Worker fputs(" System.out.println(\"mI = \" + t.mI);\n", out_);
1198*795d594fSAndroid Build Coastguard Worker fputs(" System.out.println(\"mJ = \" + t.mJ);\n", out_);
1199*795d594fSAndroid Build Coastguard Worker fputs(" System.out.println(\"mF = \" + t.mF);\n", out_);
1200*795d594fSAndroid Build Coastguard Worker fputs(" System.out.println(\"mD = \" + t.mD);\n", out_);
1201*795d594fSAndroid Build Coastguard Worker fputs(" System.out.println(\"mArray = \" + ", out_);
1202*795d594fSAndroid Build Coastguard Worker if (array_dim_ == 1) {
1203*795d594fSAndroid Build Coastguard Worker fputs("Arrays.toString(t.mArray)", out_);
1204*795d594fSAndroid Build Coastguard Worker } else {
1205*795d594fSAndroid Build Coastguard Worker fputs("Arrays.deepToString(t.mArray)", out_);
1206*795d594fSAndroid Build Coastguard Worker }
1207*795d594fSAndroid Build Coastguard Worker fputs(");\n", out_);
1208*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
1209*795d594fSAndroid Build Coastguard Worker fputs(" }\n", out_);
1210*795d594fSAndroid Build Coastguard Worker }
1211*795d594fSAndroid Build Coastguard Worker
1212*795d594fSAndroid Build Coastguard Worker // Emit a static void method.
emitStaticNopMethod()1213*795d594fSAndroid Build Coastguard Worker void emitStaticNopMethod() {
1214*795d594fSAndroid Build Coastguard Worker fputs(" public static void nop() {}\n\n", out_);
1215*795d594fSAndroid Build Coastguard Worker }
1216*795d594fSAndroid Build Coastguard Worker
1217*795d594fSAndroid Build Coastguard Worker // Emit program header. Emit command line options in the comments.
emitHeader()1218*795d594fSAndroid Build Coastguard Worker void emitHeader() {
1219*795d594fSAndroid Build Coastguard Worker fputs("\n/**\n * AOSP JFuzz Tester.\n", out_);
1220*795d594fSAndroid Build Coastguard Worker fputs(" * Automatically generated program.\n", out_);
1221*795d594fSAndroid Build Coastguard Worker fprintf(out_,
1222*795d594fSAndroid Build Coastguard Worker " * jfuzz -s %u -d %u -l %u -i %u -n %u (version %s)\n */\n\n",
1223*795d594fSAndroid Build Coastguard Worker fuzz_seed_,
1224*795d594fSAndroid Build Coastguard Worker fuzz_expr_depth_,
1225*795d594fSAndroid Build Coastguard Worker fuzz_stmt_length_,
1226*795d594fSAndroid Build Coastguard Worker fuzz_if_nest_,
1227*795d594fSAndroid Build Coastguard Worker fuzz_loop_nest_,
1228*795d594fSAndroid Build Coastguard Worker VERSION);
1229*795d594fSAndroid Build Coastguard Worker fputs("import java.util.Arrays;\n\n", out_);
1230*795d594fSAndroid Build Coastguard Worker }
1231*795d594fSAndroid Build Coastguard Worker
1232*795d594fSAndroid Build Coastguard Worker // Emit single test class with main driver.
emitTestClassWithMain()1233*795d594fSAndroid Build Coastguard Worker void emitTestClassWithMain() {
1234*795d594fSAndroid Build Coastguard Worker fputs("public class Test {\n\n", out_);
1235*795d594fSAndroid Build Coastguard Worker indentation_ += 2;
1236*795d594fSAndroid Build Coastguard Worker emitClassDecls();
1237*795d594fSAndroid Build Coastguard Worker emitFieldDecls();
1238*795d594fSAndroid Build Coastguard Worker emitArrayDecl();
1239*795d594fSAndroid Build Coastguard Worker emitTestConstructor();
1240*795d594fSAndroid Build Coastguard Worker emitTestMethod();
1241*795d594fSAndroid Build Coastguard Worker emitStaticNopMethod();
1242*795d594fSAndroid Build Coastguard Worker emitMainMethod();
1243*795d594fSAndroid Build Coastguard Worker indentation_ -= 2;
1244*795d594fSAndroid Build Coastguard Worker fputs("}\n\n", out_);
1245*795d594fSAndroid Build Coastguard Worker }
1246*795d594fSAndroid Build Coastguard Worker
1247*795d594fSAndroid Build Coastguard Worker //
1248*795d594fSAndroid Build Coastguard Worker // Random integers.
1249*795d594fSAndroid Build Coastguard Worker //
1250*795d594fSAndroid Build Coastguard Worker
1251*795d594fSAndroid Build Coastguard Worker // Return random integer.
random()1252*795d594fSAndroid Build Coastguard Worker int32_t random() {
1253*795d594fSAndroid Build Coastguard Worker return fuzz_random_engine_();
1254*795d594fSAndroid Build Coastguard Worker }
1255*795d594fSAndroid Build Coastguard Worker
1256*795d594fSAndroid Build Coastguard Worker // Return random integer in range [0,max).
random0(uint32_t max)1257*795d594fSAndroid Build Coastguard Worker uint32_t random0(uint32_t max) {
1258*795d594fSAndroid Build Coastguard Worker std::uniform_int_distribution<uint32_t> gen(0, max - 1);
1259*795d594fSAndroid Build Coastguard Worker return gen(fuzz_random_engine_);
1260*795d594fSAndroid Build Coastguard Worker }
1261*795d594fSAndroid Build Coastguard Worker
1262*795d594fSAndroid Build Coastguard Worker // Return random integer in range [1,max].
random1(uint32_t max)1263*795d594fSAndroid Build Coastguard Worker uint32_t random1(uint32_t max) {
1264*795d594fSAndroid Build Coastguard Worker std::uniform_int_distribution<uint32_t> gen(1, max);
1265*795d594fSAndroid Build Coastguard Worker return gen(fuzz_random_engine_);
1266*795d594fSAndroid Build Coastguard Worker }
1267*795d594fSAndroid Build Coastguard Worker
1268*795d594fSAndroid Build Coastguard Worker // Fuzzing parameters.
1269*795d594fSAndroid Build Coastguard Worker FILE* out_;
1270*795d594fSAndroid Build Coastguard Worker std::mt19937 fuzz_random_engine_;
1271*795d594fSAndroid Build Coastguard Worker const uint32_t fuzz_seed_;
1272*795d594fSAndroid Build Coastguard Worker const uint32_t fuzz_expr_depth_;
1273*795d594fSAndroid Build Coastguard Worker const uint32_t fuzz_stmt_length_;
1274*795d594fSAndroid Build Coastguard Worker const uint32_t fuzz_if_nest_;
1275*795d594fSAndroid Build Coastguard Worker const uint32_t fuzz_loop_nest_;
1276*795d594fSAndroid Build Coastguard Worker const uint32_t fuzz_try_nest_;
1277*795d594fSAndroid Build Coastguard Worker
1278*795d594fSAndroid Build Coastguard Worker // Return and array setup.
1279*795d594fSAndroid Build Coastguard Worker const Type return_type_;
1280*795d594fSAndroid Build Coastguard Worker const Type array_type_;
1281*795d594fSAndroid Build Coastguard Worker const uint32_t array_dim_;
1282*795d594fSAndroid Build Coastguard Worker const uint32_t array_size_;
1283*795d594fSAndroid Build Coastguard Worker
1284*795d594fSAndroid Build Coastguard Worker // Current context.
1285*795d594fSAndroid Build Coastguard Worker uint32_t indentation_;
1286*795d594fSAndroid Build Coastguard Worker uint32_t expr_depth_;
1287*795d594fSAndroid Build Coastguard Worker uint32_t stmt_length_;
1288*795d594fSAndroid Build Coastguard Worker uint32_t if_nest_;
1289*795d594fSAndroid Build Coastguard Worker uint32_t loop_nest_;
1290*795d594fSAndroid Build Coastguard Worker uint32_t switch_nest_;
1291*795d594fSAndroid Build Coastguard Worker uint32_t do_nest_;
1292*795d594fSAndroid Build Coastguard Worker uint32_t try_nest_;
1293*795d594fSAndroid Build Coastguard Worker uint32_t boolean_local_;
1294*795d594fSAndroid Build Coastguard Worker uint32_t int_local_;
1295*795d594fSAndroid Build Coastguard Worker uint32_t long_local_;
1296*795d594fSAndroid Build Coastguard Worker uint32_t float_local_;
1297*795d594fSAndroid Build Coastguard Worker uint32_t double_local_;
1298*795d594fSAndroid Build Coastguard Worker bool in_inner_;
1299*795d594fSAndroid Build Coastguard Worker };
1300*795d594fSAndroid Build Coastguard Worker
1301*795d594fSAndroid Build Coastguard Worker } // anonymous namespace
1302*795d594fSAndroid Build Coastguard Worker
main(int32_t argc,char ** argv)1303*795d594fSAndroid Build Coastguard Worker int32_t main(int32_t argc, char** argv) {
1304*795d594fSAndroid Build Coastguard Worker // Time-based seed.
1305*795d594fSAndroid Build Coastguard Worker struct timeval tp;
1306*795d594fSAndroid Build Coastguard Worker gettimeofday(&tp, nullptr);
1307*795d594fSAndroid Build Coastguard Worker
1308*795d594fSAndroid Build Coastguard Worker // Defaults.
1309*795d594fSAndroid Build Coastguard Worker uint32_t seed = (tp.tv_sec * 1000000 + tp.tv_usec);
1310*795d594fSAndroid Build Coastguard Worker uint32_t expr_depth = 1;
1311*795d594fSAndroid Build Coastguard Worker uint32_t stmt_length = 8;
1312*795d594fSAndroid Build Coastguard Worker uint32_t if_nest = 2;
1313*795d594fSAndroid Build Coastguard Worker uint32_t loop_nest = 3;
1314*795d594fSAndroid Build Coastguard Worker uint32_t try_nest = 2;
1315*795d594fSAndroid Build Coastguard Worker
1316*795d594fSAndroid Build Coastguard Worker // Parse options.
1317*795d594fSAndroid Build Coastguard Worker while (1) {
1318*795d594fSAndroid Build Coastguard Worker int32_t option = getopt(argc, argv, "s:d:l:i:n:vh");
1319*795d594fSAndroid Build Coastguard Worker if (option < 0) {
1320*795d594fSAndroid Build Coastguard Worker break; // done
1321*795d594fSAndroid Build Coastguard Worker }
1322*795d594fSAndroid Build Coastguard Worker switch (option) {
1323*795d594fSAndroid Build Coastguard Worker case 's':
1324*795d594fSAndroid Build Coastguard Worker seed = strtoul(optarg, nullptr, 0); // deterministic seed
1325*795d594fSAndroid Build Coastguard Worker break;
1326*795d594fSAndroid Build Coastguard Worker case 'd':
1327*795d594fSAndroid Build Coastguard Worker expr_depth = strtoul(optarg, nullptr, 0);
1328*795d594fSAndroid Build Coastguard Worker break;
1329*795d594fSAndroid Build Coastguard Worker case 'l':
1330*795d594fSAndroid Build Coastguard Worker stmt_length = strtoul(optarg, nullptr, 0);
1331*795d594fSAndroid Build Coastguard Worker break;
1332*795d594fSAndroid Build Coastguard Worker case 'i':
1333*795d594fSAndroid Build Coastguard Worker if_nest = strtoul(optarg, nullptr, 0);
1334*795d594fSAndroid Build Coastguard Worker break;
1335*795d594fSAndroid Build Coastguard Worker case 'n':
1336*795d594fSAndroid Build Coastguard Worker loop_nest = strtoul(optarg, nullptr, 0);
1337*795d594fSAndroid Build Coastguard Worker break;
1338*795d594fSAndroid Build Coastguard Worker case 't':
1339*795d594fSAndroid Build Coastguard Worker try_nest = strtoul(optarg, nullptr, 0);
1340*795d594fSAndroid Build Coastguard Worker break;
1341*795d594fSAndroid Build Coastguard Worker case 'v':
1342*795d594fSAndroid Build Coastguard Worker fprintf(stderr, "jfuzz version %s\n", VERSION);
1343*795d594fSAndroid Build Coastguard Worker return 0;
1344*795d594fSAndroid Build Coastguard Worker case 'h':
1345*795d594fSAndroid Build Coastguard Worker default:
1346*795d594fSAndroid Build Coastguard Worker fprintf(stderr,
1347*795d594fSAndroid Build Coastguard Worker "usage: %s [-s seed] "
1348*795d594fSAndroid Build Coastguard Worker "[-d expr-depth] [-l stmt-length] "
1349*795d594fSAndroid Build Coastguard Worker "[-i if-nest] [-n loop-nest] [-t try-nest] [-v] [-h]\n",
1350*795d594fSAndroid Build Coastguard Worker argv[0]);
1351*795d594fSAndroid Build Coastguard Worker return 1;
1352*795d594fSAndroid Build Coastguard Worker }
1353*795d594fSAndroid Build Coastguard Worker }
1354*795d594fSAndroid Build Coastguard Worker
1355*795d594fSAndroid Build Coastguard Worker // Seed global random generator.
1356*795d594fSAndroid Build Coastguard Worker srand(seed);
1357*795d594fSAndroid Build Coastguard Worker
1358*795d594fSAndroid Build Coastguard Worker // Generate fuzzed program.
1359*795d594fSAndroid Build Coastguard Worker JFuzz fuzz(stdout, seed, expr_depth, stmt_length, if_nest, loop_nest, try_nest);
1360*795d594fSAndroid Build Coastguard Worker fuzz.emitProgram();
1361*795d594fSAndroid Build Coastguard Worker return 0;
1362*795d594fSAndroid Build Coastguard Worker }
1363