blob: 9036b2bba9855f024807bfb04250628a3acf2cfb [file] [log] [blame]
Mike Stump46ae64f2010-01-07 18:58:28 +00001#include <stdio.h>
2#include <stdlib.h>
3
4#define N_FIELDS 7
5#define N_FUNCS 128
6#define FUNCSPACING 10
7#define N_STRUCTS 300 /* 1280 */
8// FIXME: Need final overrider logic for 3 or more if we turn on virtual base
9// class dups
10#define N_BASES 30 /* 30 */
11
12const char *simple_types[] = { "bool", "char", "short", "int", "float",
13 "double", "long double", "wchar_t", "void *",
14 "char *"
15};
16
17void gl(const char *c) {
18 printf("%s\n", c);
19}
20
21void g(const char *c) {
22 printf("%s", c);
23}
24
25void g(int i) {
26 printf("%d", i);
27}
28
Mike Stump82f0be92010-01-07 20:55:28 +000029int uuid = 0;
Mike Stump46ae64f2010-01-07 18:58:28 +000030char base_present[N_STRUCTS][N_STRUCTS];
31
32bool is_ambiguous(int s, int base) {
33 for (int i = 0; i < N_STRUCTS; ++i) {
34 if ((base_present[base][i] & base_present[s][i])
35 // FIXME: todo this, we need final overrider additions
36 /*== 1 */)
37 return true;
38 }
39 return false;
40}
41
42void add_bases(int s, int base) {
43 for (int i = 0; i < N_STRUCTS; ++i)
44 base_present[s][i] |= base_present[base][i];
45}
46
47void gs(int s) {
48 bool polymorphic = false;
49
50 static int bases[N_BASES];
51 int i_bases = random() % (N_BASES*2);
52 if (i_bases >= N_BASES)
53 // PARAM: 1/2 of all clases should have no bases
54 i_bases = 0;
55 int n_bases = 0;
56 bool first_base = true;
57
58 // PARAM: 3/4 of all should be class, the rest are structs
59 if (random() % 4 == 0)
60 g("struct s");
61 else
62 g("class s");
63 g(s);
64 int old_base = -1;
65 if (s == 0)
66 i_bases = 0;
67 while (i_bases) {
68 --i_bases;
69 int base = random() % s;
70 if (!base_present[s][base]) {
71 if (is_ambiguous(s, base))
72 continue;
73 if (first_base) {
74 first_base = false;
75 g(": ");
76 } else
77 g(", ");
78 int base_type = 1;
79 if (random()%8 == 0) {
80 // PARAM: 1/8th the bases are virtual
81 g("virtual ");
82 polymorphic = true;
83 base_type = 3;
84 }
85 switch (random()%8) {
86 case 0:
87 case 1:
88 case 2:
89 case 3:
90 break;
91 case 4:
92 case 5:
93 g("public "); break;
94 case 6:
95 g("private "); break;
96 case 7:
97 g("protected "); break;
98 }
99 g("s");
100 add_bases(s, base);
101 bases[n_bases] = base;
102 base_present[s][base] = base_type;
103 ++n_bases;
104 g(base);
105 old_base = base;
106 }
107 }
108 gl(" {");
109
110 /* Fields */
111 int n_fields = random() % (N_FIELDS*4);
112 // PARAM: 3/4 of all structs should have no members
113 if (n_fields >= N_FIELDS)
114 n_fields = 0;
115 for (int i = 0; i < n_fields; ++i) {
116 int t = random() % (sizeof(simple_types) / sizeof(simple_types[0]));
117 g(" "); g(simple_types[t]); g(" field"); g(i); gl(";");
118 }
119
120 /* Virtual functions */
121 static int funcs[N_FUNCS];
Mike Stump82f0be92010-01-07 20:55:28 +0000122 // PARAM: 1/2 of all structs should have no virtual functions
123 int n_funcs = random() % (N_FUNCS*2);
124 if (n_funcs > N_FUNCS)
125 n_funcs = 0;
Mike Stump46ae64f2010-01-07 18:58:28 +0000126 int old_func = -1;
127 for (int i = 0; i < n_funcs; ++i) {
128 int fn = old_func + random() % FUNCSPACING + 1;
129 funcs[i] = fn;
Mike Stump82f0be92010-01-07 20:55:28 +0000130 g(" virtual void fun"); g(fn); g("(char *t) { mix(\"vfn this offset\", (char *)this - t); mix(\"vfn uuid\", "); g(++uuid); gl("); }");
Mike Stump46ae64f2010-01-07 18:58:28 +0000131 old_func = fn;
132 }
133
134 gl("public:");
135 gl(" void calc(char *t) {");
136
137 // mix in the type number
Mike Stump365d6382010-01-07 19:39:43 +0000138 g(" mix(\"type num\", "); g(s); gl(");");
Mike Stump46ae64f2010-01-07 18:58:28 +0000139 // mix in the size
Mike Stump365d6382010-01-07 19:39:43 +0000140 g(" mix(\"type size\", sizeof (s"); g(s); gl("));");
Mike Stump46ae64f2010-01-07 18:58:28 +0000141 // mix in the this offset
Mike Stump365d6382010-01-07 19:39:43 +0000142 gl(" mix(\"subobject offset\", (char *)this - t);");
Mike Stump46ae64f2010-01-07 18:58:28 +0000143 if (n_funcs)
144 polymorphic = true;
145 if (polymorphic) {
146 // mix in offset to the complete object under construction
Mike Stump365d6382010-01-07 19:39:43 +0000147 gl(" mix(\"real top v current top\", t - (char *)dynamic_cast<void*>(this));");
Mike Stump46ae64f2010-01-07 18:58:28 +0000148 }
149
150 /* check base layout and overrides */
151 for (int i = 0; i < n_bases; ++i) {
152 g(" calc_s"); g(bases[i]); gl("(t);");
153 }
154
155 if (polymorphic) {
156 /* check dynamic_cast to each direct base */
157 for (int i = 0; i < n_bases; ++i) {
158 g(" if ((char *)dynamic_cast<s"); g(bases[i]); gl("*>(this))");
Mike Stump365d6382010-01-07 19:39:43 +0000159 g(" mix(\"base dyn cast\", t - (char *)dynamic_cast<s"); g(bases[i]); gl("*>(this));");
Mike Stump82f0be92010-01-07 20:55:28 +0000160 g(" else mix(\"no dyncast\", "); g(++uuid); gl(");");
Mike Stump46ae64f2010-01-07 18:58:28 +0000161 }
162 }
163
164 /* check field layout */
165 for (int i = 0; i < n_fields; ++i) {
Mike Stump365d6382010-01-07 19:39:43 +0000166 g(" mix(\"field offset\", (char *)&field"); g(i); gl(" - (char *)this);");
Mike Stump46ae64f2010-01-07 18:58:28 +0000167 }
Mike Stump82f0be92010-01-07 20:55:28 +0000168 if (n_fields == 0) {
169 g(" mix(\"no fields\", "); g(++uuid); gl(");");
170 }
Mike Stump46ae64f2010-01-07 18:58:28 +0000171
172 /* check functions */
173 for (int i = 0; i < n_funcs; ++i) {
174 g(" fun"); g(funcs[i]); gl("(t);");
175 }
Mike Stump82f0be92010-01-07 20:55:28 +0000176 if (n_funcs == 0) {
177 g(" mix(\"no funcs\", "); g(++uuid); gl(");");
178 }
Mike Stump46ae64f2010-01-07 18:58:28 +0000179
180 gl(" }");
181
182 // default ctor
183 g(" s"); g(s); g("() ");
184 first_base = true;
185 for (int i = 0; i < n_bases; ++i) {
186 if (first_base) {
187 g(": ");
188 first_base = false;
189 } else
190 g(", ");
191 g("s"); g(bases[i]); g("((char *)this)");
192 }
193 gl(" { calc((char *)this); }");
194 g(" ~s"); g(s); gl("() { calc((char *)this); }");
195
196 // ctor with this to the complete object
197 g(" s"); g(s); gl("(char *t) { calc(t); }");
198 g(" void calc_s"); g(s); gl("(char *t) { calc(t); }");
199 g("} a"); g(s); gl(";");
200}
201
202main(int argc, char **argv) {
203 unsigned seed = 0;
204 char state[16];
205 if (argc > 1)
206 seed = atol(argv[1]);
207
208 initstate(seed, state, sizeof(state));
209 gl("extern \"C\" int printf(const char *...);");
210 gl("");
211 gl("long long sum;");
Mike Stump365d6382010-01-07 19:39:43 +0000212 gl("void mix(const char *desc, long long i) {");
Mike Stump46ae64f2010-01-07 18:58:28 +0000213 // If this ever becomes too slow, we can remove this after we improve the
214 // mixing function
Mike Stump365d6382010-01-07 19:39:43 +0000215 gl(" printf(\"%s: %lld\\n\", desc, i);");
Mike Stump46ae64f2010-01-07 18:58:28 +0000216 gl(" sum += ((sum ^ i) << 3) + (sum<<1) - i;");
217 gl("}");
Mike Stump46ae64f2010-01-07 18:58:28 +0000218 gl("");
219 // PARAM: Randomly size testcases or large testcases?
220 int n_structs = /* random() % */ N_STRUCTS;
221 for (int i = 0; i < n_structs; ++i)
222 gs(i);
223 gl("int main() {");
224 gl(" printf(\"%llx\\n\", sum);");
225 gl("}");
226 return 0;
227}