xref: /aosp_15_r20/art/tools/jfuzz/jfuzz.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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